1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2020 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker *
4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker *
8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker *
10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker */
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/perf/event_config.h"
18*6dbdd20aSAndroid Build Coastguard Worker
19*6dbdd20aSAndroid Build Coastguard Worker #include <linux/perf_event.h>
20*6dbdd20aSAndroid Build Coastguard Worker #include <time.h>
21*6dbdd20aSAndroid Build Coastguard Worker
22*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/Regs.h>
23*6dbdd20aSAndroid Build Coastguard Worker #include <optional>
24*6dbdd20aSAndroid Build Coastguard Worker #include <vector>
25*6dbdd20aSAndroid Build Coastguard Worker
26*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/flat_set.h"
27*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/utils.h"
28*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/perf/regs_parsing.h"
29*6dbdd20aSAndroid Build Coastguard Worker
30*6dbdd20aSAndroid Build Coastguard Worker #include "protos/perfetto/common/perf_events.gen.h"
31*6dbdd20aSAndroid Build Coastguard Worker #include "protos/perfetto/config/profiling/perf_event_config.gen.h"
32*6dbdd20aSAndroid Build Coastguard Worker
33*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
34*6dbdd20aSAndroid Build Coastguard Worker namespace profiling {
35*6dbdd20aSAndroid Build Coastguard Worker
36*6dbdd20aSAndroid Build Coastguard Worker namespace {
37*6dbdd20aSAndroid Build Coastguard Worker constexpr uint64_t kDefaultSamplingFrequencyHz = 10;
38*6dbdd20aSAndroid Build Coastguard Worker constexpr uint32_t kDefaultDataPagesPerRingBuffer = 256; // 1 MB: 256x 4k pages
39*6dbdd20aSAndroid Build Coastguard Worker constexpr uint32_t kDefaultReadTickPeriodMs = 100;
40*6dbdd20aSAndroid Build Coastguard Worker constexpr uint32_t kDefaultRemoteDescriptorTimeoutMs = 100;
41*6dbdd20aSAndroid Build Coastguard Worker
42*6dbdd20aSAndroid Build Coastguard Worker // Acceptable forms: "sched/sched_switch" or "sched:sched_switch".
SplitTracepointString(const std::string & input)43*6dbdd20aSAndroid Build Coastguard Worker std::pair<std::string, std::string> SplitTracepointString(
44*6dbdd20aSAndroid Build Coastguard Worker const std::string& input) {
45*6dbdd20aSAndroid Build Coastguard Worker auto slash_pos = input.find("/");
46*6dbdd20aSAndroid Build Coastguard Worker if (slash_pos != std::string::npos)
47*6dbdd20aSAndroid Build Coastguard Worker return std::make_pair(input.substr(0, slash_pos),
48*6dbdd20aSAndroid Build Coastguard Worker input.substr(slash_pos + 1));
49*6dbdd20aSAndroid Build Coastguard Worker
50*6dbdd20aSAndroid Build Coastguard Worker auto colon_pos = input.find(":");
51*6dbdd20aSAndroid Build Coastguard Worker if (colon_pos != std::string::npos)
52*6dbdd20aSAndroid Build Coastguard Worker return std::make_pair(input.substr(0, colon_pos),
53*6dbdd20aSAndroid Build Coastguard Worker input.substr(colon_pos + 1));
54*6dbdd20aSAndroid Build Coastguard Worker
55*6dbdd20aSAndroid Build Coastguard Worker return std::make_pair("", input);
56*6dbdd20aSAndroid Build Coastguard Worker }
57*6dbdd20aSAndroid Build Coastguard Worker
58*6dbdd20aSAndroid Build Coastguard Worker // If set, the returned id is guaranteed to be non-zero.
ParseTracepointAndResolveId(const protos::gen::PerfEvents::Tracepoint & tracepoint,EventConfig::tracepoint_id_fn_t tracepoint_id_lookup)59*6dbdd20aSAndroid Build Coastguard Worker std::optional<uint32_t> ParseTracepointAndResolveId(
60*6dbdd20aSAndroid Build Coastguard Worker const protos::gen::PerfEvents::Tracepoint& tracepoint,
61*6dbdd20aSAndroid Build Coastguard Worker EventConfig::tracepoint_id_fn_t tracepoint_id_lookup) {
62*6dbdd20aSAndroid Build Coastguard Worker std::string full_name = tracepoint.name();
63*6dbdd20aSAndroid Build Coastguard Worker std::string tp_group;
64*6dbdd20aSAndroid Build Coastguard Worker std::string tp_name;
65*6dbdd20aSAndroid Build Coastguard Worker std::tie(tp_group, tp_name) = SplitTracepointString(full_name);
66*6dbdd20aSAndroid Build Coastguard Worker if (tp_group.empty() || tp_name.empty()) {
67*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG(
68*6dbdd20aSAndroid Build Coastguard Worker "Invalid tracepoint format: %s. Should be a full path like "
69*6dbdd20aSAndroid Build Coastguard Worker "sched:sched_switch or sched/sched_switch.",
70*6dbdd20aSAndroid Build Coastguard Worker full_name.c_str());
71*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
72*6dbdd20aSAndroid Build Coastguard Worker }
73*6dbdd20aSAndroid Build Coastguard Worker
74*6dbdd20aSAndroid Build Coastguard Worker uint32_t tracepoint_id = tracepoint_id_lookup(tp_group, tp_name);
75*6dbdd20aSAndroid Build Coastguard Worker if (!tracepoint_id) {
76*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG(
77*6dbdd20aSAndroid Build Coastguard Worker "Failed to resolve tracepoint %s to its id. Check that tracefs is "
78*6dbdd20aSAndroid Build Coastguard Worker "accessible and the event exists.",
79*6dbdd20aSAndroid Build Coastguard Worker full_name.c_str());
80*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
81*6dbdd20aSAndroid Build Coastguard Worker }
82*6dbdd20aSAndroid Build Coastguard Worker return std::make_optional(tracepoint_id);
83*6dbdd20aSAndroid Build Coastguard Worker }
84*6dbdd20aSAndroid Build Coastguard Worker
85*6dbdd20aSAndroid Build Coastguard Worker // |T| is either gen::PerfEventConfig or gen::PerfEventConfig::Scope.
86*6dbdd20aSAndroid Build Coastguard Worker // Note: the semantics of target_cmdline and exclude_cmdline were changed since
87*6dbdd20aSAndroid Build Coastguard Worker // their original introduction. They used to be put through a canonicalization
88*6dbdd20aSAndroid Build Coastguard Worker // function that simplified them to the binary name alone. We no longer do this,
89*6dbdd20aSAndroid Build Coastguard Worker // regardless of whether we're parsing an old-style config. The overall outcome
90*6dbdd20aSAndroid Build Coastguard Worker // shouldn't change for almost all existing uses.
91*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
ParseTargetFilter(const T & cfg,std::optional<ProcessSharding> process_sharding)92*6dbdd20aSAndroid Build Coastguard Worker TargetFilter ParseTargetFilter(
93*6dbdd20aSAndroid Build Coastguard Worker const T& cfg,
94*6dbdd20aSAndroid Build Coastguard Worker std::optional<ProcessSharding> process_sharding) {
95*6dbdd20aSAndroid Build Coastguard Worker TargetFilter filter;
96*6dbdd20aSAndroid Build Coastguard Worker for (const auto& str : cfg.target_cmdline()) {
97*6dbdd20aSAndroid Build Coastguard Worker filter.cmdlines.push_back(str);
98*6dbdd20aSAndroid Build Coastguard Worker }
99*6dbdd20aSAndroid Build Coastguard Worker for (const auto& str : cfg.exclude_cmdline()) {
100*6dbdd20aSAndroid Build Coastguard Worker filter.exclude_cmdlines.push_back(str);
101*6dbdd20aSAndroid Build Coastguard Worker }
102*6dbdd20aSAndroid Build Coastguard Worker for (const int32_t pid : cfg.target_pid()) {
103*6dbdd20aSAndroid Build Coastguard Worker filter.pids.insert(pid);
104*6dbdd20aSAndroid Build Coastguard Worker }
105*6dbdd20aSAndroid Build Coastguard Worker for (const int32_t pid : cfg.exclude_pid()) {
106*6dbdd20aSAndroid Build Coastguard Worker filter.exclude_pids.insert(pid);
107*6dbdd20aSAndroid Build Coastguard Worker }
108*6dbdd20aSAndroid Build Coastguard Worker filter.additional_cmdline_count = cfg.additional_cmdline_count();
109*6dbdd20aSAndroid Build Coastguard Worker filter.process_sharding = process_sharding;
110*6dbdd20aSAndroid Build Coastguard Worker return filter;
111*6dbdd20aSAndroid Build Coastguard Worker }
112*6dbdd20aSAndroid Build Coastguard Worker
IsPowerOfTwo(size_t v)113*6dbdd20aSAndroid Build Coastguard Worker constexpr bool IsPowerOfTwo(size_t v) {
114*6dbdd20aSAndroid Build Coastguard Worker return (v != 0 && ((v & (v - 1)) == 0));
115*6dbdd20aSAndroid Build Coastguard Worker }
116*6dbdd20aSAndroid Build Coastguard Worker
117*6dbdd20aSAndroid Build Coastguard Worker // returns |std::nullopt| if the input is invalid.
ChooseActualRingBufferPages(uint32_t config_value)118*6dbdd20aSAndroid Build Coastguard Worker std::optional<uint32_t> ChooseActualRingBufferPages(uint32_t config_value) {
119*6dbdd20aSAndroid Build Coastguard Worker if (!config_value) {
120*6dbdd20aSAndroid Build Coastguard Worker static_assert(IsPowerOfTwo(kDefaultDataPagesPerRingBuffer), "");
121*6dbdd20aSAndroid Build Coastguard Worker return std::make_optional(kDefaultDataPagesPerRingBuffer);
122*6dbdd20aSAndroid Build Coastguard Worker }
123*6dbdd20aSAndroid Build Coastguard Worker
124*6dbdd20aSAndroid Build Coastguard Worker if (!IsPowerOfTwo(config_value)) {
125*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG("kernel buffer size must be a power of two pages");
126*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
127*6dbdd20aSAndroid Build Coastguard Worker }
128*6dbdd20aSAndroid Build Coastguard Worker
129*6dbdd20aSAndroid Build Coastguard Worker return std::make_optional(config_value);
130*6dbdd20aSAndroid Build Coastguard Worker }
131*6dbdd20aSAndroid Build Coastguard Worker
ToPerfCounter(std::string name,protos::gen::PerfEvents::Counter pb_enum)132*6dbdd20aSAndroid Build Coastguard Worker std::optional<PerfCounter> ToPerfCounter(
133*6dbdd20aSAndroid Build Coastguard Worker std::string name,
134*6dbdd20aSAndroid Build Coastguard Worker protos::gen::PerfEvents::Counter pb_enum) {
135*6dbdd20aSAndroid Build Coastguard Worker using protos::gen::PerfEvents;
136*6dbdd20aSAndroid Build Coastguard Worker switch (static_cast<int>(pb_enum)) { // cast to pacify -Wswitch-enum
137*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::SW_CPU_CLOCK:
138*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(name, PerfEvents::SW_CPU_CLOCK,
139*6dbdd20aSAndroid Build Coastguard Worker PERF_TYPE_SOFTWARE,
140*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_SW_CPU_CLOCK);
141*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::SW_PAGE_FAULTS:
142*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(name, PerfEvents::SW_PAGE_FAULTS,
143*6dbdd20aSAndroid Build Coastguard Worker PERF_TYPE_SOFTWARE,
144*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_SW_PAGE_FAULTS);
145*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::SW_TASK_CLOCK:
146*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(name, PerfEvents::SW_TASK_CLOCK,
147*6dbdd20aSAndroid Build Coastguard Worker PERF_TYPE_SOFTWARE,
148*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_SW_TASK_CLOCK);
149*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::SW_CONTEXT_SWITCHES:
150*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(name, PerfEvents::SW_CONTEXT_SWITCHES,
151*6dbdd20aSAndroid Build Coastguard Worker PERF_TYPE_SOFTWARE,
152*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_SW_CONTEXT_SWITCHES);
153*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::SW_CPU_MIGRATIONS:
154*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(name, PerfEvents::SW_CPU_MIGRATIONS,
155*6dbdd20aSAndroid Build Coastguard Worker PERF_TYPE_SOFTWARE,
156*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_SW_CPU_MIGRATIONS);
157*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::SW_PAGE_FAULTS_MIN:
158*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(name, PerfEvents::SW_PAGE_FAULTS_MIN,
159*6dbdd20aSAndroid Build Coastguard Worker PERF_TYPE_SOFTWARE,
160*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_SW_PAGE_FAULTS_MIN);
161*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::SW_PAGE_FAULTS_MAJ:
162*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(name, PerfEvents::SW_PAGE_FAULTS_MAJ,
163*6dbdd20aSAndroid Build Coastguard Worker PERF_TYPE_SOFTWARE,
164*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_SW_PAGE_FAULTS_MAJ);
165*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::SW_ALIGNMENT_FAULTS:
166*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(name, PerfEvents::SW_ALIGNMENT_FAULTS,
167*6dbdd20aSAndroid Build Coastguard Worker PERF_TYPE_SOFTWARE,
168*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_SW_ALIGNMENT_FAULTS);
169*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::SW_EMULATION_FAULTS:
170*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(name, PerfEvents::SW_EMULATION_FAULTS,
171*6dbdd20aSAndroid Build Coastguard Worker PERF_TYPE_SOFTWARE,
172*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_SW_EMULATION_FAULTS);
173*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::SW_DUMMY:
174*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(
175*6dbdd20aSAndroid Build Coastguard Worker name, PerfEvents::SW_DUMMY, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY);
176*6dbdd20aSAndroid Build Coastguard Worker
177*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::HW_CPU_CYCLES:
178*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(name, PerfEvents::HW_CPU_CYCLES,
179*6dbdd20aSAndroid Build Coastguard Worker PERF_TYPE_HARDWARE,
180*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_HW_CPU_CYCLES);
181*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::HW_INSTRUCTIONS:
182*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(name, PerfEvents::HW_INSTRUCTIONS,
183*6dbdd20aSAndroid Build Coastguard Worker PERF_TYPE_HARDWARE,
184*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_HW_INSTRUCTIONS);
185*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::HW_CACHE_REFERENCES:
186*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(name, PerfEvents::HW_CACHE_REFERENCES,
187*6dbdd20aSAndroid Build Coastguard Worker PERF_TYPE_HARDWARE,
188*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_HW_CACHE_REFERENCES);
189*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::HW_CACHE_MISSES:
190*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(name, PerfEvents::HW_CACHE_MISSES,
191*6dbdd20aSAndroid Build Coastguard Worker PERF_TYPE_HARDWARE,
192*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_HW_CACHE_MISSES);
193*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::HW_BRANCH_INSTRUCTIONS:
194*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(
195*6dbdd20aSAndroid Build Coastguard Worker name, PerfEvents::HW_BRANCH_INSTRUCTIONS, PERF_TYPE_HARDWARE,
196*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
197*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::HW_BRANCH_MISSES:
198*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(name, PerfEvents::HW_BRANCH_MISSES,
199*6dbdd20aSAndroid Build Coastguard Worker PERF_TYPE_HARDWARE,
200*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_HW_BRANCH_MISSES);
201*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::HW_BUS_CYCLES:
202*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(name, PerfEvents::HW_BUS_CYCLES,
203*6dbdd20aSAndroid Build Coastguard Worker PERF_TYPE_HARDWARE,
204*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_HW_BUS_CYCLES);
205*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::HW_STALLED_CYCLES_FRONTEND:
206*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(
207*6dbdd20aSAndroid Build Coastguard Worker name, PerfEvents::HW_STALLED_CYCLES_FRONTEND, PERF_TYPE_HARDWARE,
208*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_HW_STALLED_CYCLES_FRONTEND);
209*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::HW_STALLED_CYCLES_BACKEND:
210*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(
211*6dbdd20aSAndroid Build Coastguard Worker name, PerfEvents::HW_STALLED_CYCLES_BACKEND, PERF_TYPE_HARDWARE,
212*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_HW_STALLED_CYCLES_BACKEND);
213*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::HW_REF_CPU_CYCLES:
214*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(name, PerfEvents::HW_REF_CPU_CYCLES,
215*6dbdd20aSAndroid Build Coastguard Worker PERF_TYPE_HARDWARE,
216*6dbdd20aSAndroid Build Coastguard Worker PERF_COUNT_HW_REF_CPU_CYCLES);
217*6dbdd20aSAndroid Build Coastguard Worker
218*6dbdd20aSAndroid Build Coastguard Worker default:
219*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG("Unrecognised PerfEvents::Counter enum value: %zu",
220*6dbdd20aSAndroid Build Coastguard Worker static_cast<size_t>(pb_enum));
221*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
222*6dbdd20aSAndroid Build Coastguard Worker }
223*6dbdd20aSAndroid Build Coastguard Worker }
224*6dbdd20aSAndroid Build Coastguard Worker
ToClockId(protos::gen::PerfEvents::PerfClock pb_enum)225*6dbdd20aSAndroid Build Coastguard Worker int32_t ToClockId(protos::gen::PerfEvents::PerfClock pb_enum) {
226*6dbdd20aSAndroid Build Coastguard Worker using protos::gen::PerfEvents;
227*6dbdd20aSAndroid Build Coastguard Worker switch (static_cast<int>(pb_enum)) { // cast to pacify -Wswitch-enum
228*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::PERF_CLOCK_REALTIME:
229*6dbdd20aSAndroid Build Coastguard Worker return CLOCK_REALTIME;
230*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::PERF_CLOCK_MONOTONIC:
231*6dbdd20aSAndroid Build Coastguard Worker return CLOCK_MONOTONIC;
232*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::PERF_CLOCK_MONOTONIC_RAW:
233*6dbdd20aSAndroid Build Coastguard Worker return CLOCK_MONOTONIC_RAW;
234*6dbdd20aSAndroid Build Coastguard Worker case PerfEvents::PERF_CLOCK_BOOTTIME:
235*6dbdd20aSAndroid Build Coastguard Worker return CLOCK_BOOTTIME;
236*6dbdd20aSAndroid Build Coastguard Worker // Default to a monotonic clock since it should be compatible with all types
237*6dbdd20aSAndroid Build Coastguard Worker // of events. Whereas boottime cannot be used with hardware events due to
238*6dbdd20aSAndroid Build Coastguard Worker // potential access within non-maskable interrupts.
239*6dbdd20aSAndroid Build Coastguard Worker default:
240*6dbdd20aSAndroid Build Coastguard Worker return CLOCK_MONOTONIC_RAW;
241*6dbdd20aSAndroid Build Coastguard Worker }
242*6dbdd20aSAndroid Build Coastguard Worker }
243*6dbdd20aSAndroid Build Coastguard Worker
244*6dbdd20aSAndroid Build Coastguard Worker // Build a singular event from an event description provided by either
245*6dbdd20aSAndroid Build Coastguard Worker // a PerfEvents::Timebase or a FollowerEvent materialized by the
246*6dbdd20aSAndroid Build Coastguard Worker // polymorphic parameter event_desc.
247*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
MakePerfCounter(EventConfig::tracepoint_id_fn_t & tracepoint_id_lookup,const std::string & name,const T & event_desc)248*6dbdd20aSAndroid Build Coastguard Worker std::optional<PerfCounter> MakePerfCounter(
249*6dbdd20aSAndroid Build Coastguard Worker EventConfig::tracepoint_id_fn_t& tracepoint_id_lookup,
250*6dbdd20aSAndroid Build Coastguard Worker const std::string& name,
251*6dbdd20aSAndroid Build Coastguard Worker const T& event_desc) {
252*6dbdd20aSAndroid Build Coastguard Worker if (event_desc.has_counter()) {
253*6dbdd20aSAndroid Build Coastguard Worker auto maybe_counter = ToPerfCounter(name, event_desc.counter());
254*6dbdd20aSAndroid Build Coastguard Worker if (!maybe_counter)
255*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
256*6dbdd20aSAndroid Build Coastguard Worker return *maybe_counter;
257*6dbdd20aSAndroid Build Coastguard Worker } else if (event_desc.has_tracepoint()) {
258*6dbdd20aSAndroid Build Coastguard Worker const auto& tracepoint_pb = event_desc.tracepoint();
259*6dbdd20aSAndroid Build Coastguard Worker std::optional<uint32_t> maybe_id =
260*6dbdd20aSAndroid Build Coastguard Worker ParseTracepointAndResolveId(tracepoint_pb, tracepoint_id_lookup);
261*6dbdd20aSAndroid Build Coastguard Worker if (!maybe_id)
262*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
263*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::Tracepoint(name, tracepoint_pb.name(),
264*6dbdd20aSAndroid Build Coastguard Worker tracepoint_pb.filter(), *maybe_id);
265*6dbdd20aSAndroid Build Coastguard Worker } else if (event_desc.has_raw_event()) {
266*6dbdd20aSAndroid Build Coastguard Worker const auto& raw = event_desc.raw_event();
267*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::RawEvent(name, raw.type(), raw.config(), raw.config1(),
268*6dbdd20aSAndroid Build Coastguard Worker raw.config2());
269*6dbdd20aSAndroid Build Coastguard Worker } else {
270*6dbdd20aSAndroid Build Coastguard Worker return PerfCounter::BuiltinCounter(
271*6dbdd20aSAndroid Build Coastguard Worker name, protos::gen::PerfEvents::PerfEvents::SW_CPU_CLOCK,
272*6dbdd20aSAndroid Build Coastguard Worker PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK);
273*6dbdd20aSAndroid Build Coastguard Worker }
274*6dbdd20aSAndroid Build Coastguard Worker }
275*6dbdd20aSAndroid Build Coastguard Worker
IsSupportedUnwindMode(protos::gen::PerfEventConfig::UnwindMode unwind_mode)276*6dbdd20aSAndroid Build Coastguard Worker bool IsSupportedUnwindMode(
277*6dbdd20aSAndroid Build Coastguard Worker protos::gen::PerfEventConfig::UnwindMode unwind_mode) {
278*6dbdd20aSAndroid Build Coastguard Worker using protos::gen::PerfEventConfig;
279*6dbdd20aSAndroid Build Coastguard Worker switch (static_cast<int>(unwind_mode)) { // cast to pacify -Wswitch-enum
280*6dbdd20aSAndroid Build Coastguard Worker case PerfEventConfig::UNWIND_UNKNOWN:
281*6dbdd20aSAndroid Build Coastguard Worker case PerfEventConfig::UNWIND_SKIP:
282*6dbdd20aSAndroid Build Coastguard Worker case PerfEventConfig::UNWIND_DWARF:
283*6dbdd20aSAndroid Build Coastguard Worker case PerfEventConfig::UNWIND_FRAME_POINTER:
284*6dbdd20aSAndroid Build Coastguard Worker return true;
285*6dbdd20aSAndroid Build Coastguard Worker default:
286*6dbdd20aSAndroid Build Coastguard Worker return false;
287*6dbdd20aSAndroid Build Coastguard Worker }
288*6dbdd20aSAndroid Build Coastguard Worker }
289*6dbdd20aSAndroid Build Coastguard Worker
290*6dbdd20aSAndroid Build Coastguard Worker } // namespace
291*6dbdd20aSAndroid Build Coastguard Worker
292*6dbdd20aSAndroid Build Coastguard Worker // static
BuiltinCounter(std::string name,protos::gen::PerfEvents::Counter counter,uint32_t type,uint64_t config)293*6dbdd20aSAndroid Build Coastguard Worker PerfCounter PerfCounter::BuiltinCounter(
294*6dbdd20aSAndroid Build Coastguard Worker std::string name,
295*6dbdd20aSAndroid Build Coastguard Worker protos::gen::PerfEvents::Counter counter,
296*6dbdd20aSAndroid Build Coastguard Worker uint32_t type,
297*6dbdd20aSAndroid Build Coastguard Worker uint64_t config) {
298*6dbdd20aSAndroid Build Coastguard Worker PerfCounter ret;
299*6dbdd20aSAndroid Build Coastguard Worker ret.type = PerfCounter::Type::kBuiltinCounter;
300*6dbdd20aSAndroid Build Coastguard Worker ret.counter = counter;
301*6dbdd20aSAndroid Build Coastguard Worker ret.name = std::move(name);
302*6dbdd20aSAndroid Build Coastguard Worker
303*6dbdd20aSAndroid Build Coastguard Worker ret.attr_type = type;
304*6dbdd20aSAndroid Build Coastguard Worker ret.attr_config = config;
305*6dbdd20aSAndroid Build Coastguard Worker // none of the builtin counters require config1 and config2 at the moment
306*6dbdd20aSAndroid Build Coastguard Worker return ret;
307*6dbdd20aSAndroid Build Coastguard Worker }
308*6dbdd20aSAndroid Build Coastguard Worker
309*6dbdd20aSAndroid Build Coastguard Worker // static
Tracepoint(std::string name,std::string tracepoint_name,std::string tracepoint_filter,uint64_t id)310*6dbdd20aSAndroid Build Coastguard Worker PerfCounter PerfCounter::Tracepoint(std::string name,
311*6dbdd20aSAndroid Build Coastguard Worker std::string tracepoint_name,
312*6dbdd20aSAndroid Build Coastguard Worker std::string tracepoint_filter,
313*6dbdd20aSAndroid Build Coastguard Worker uint64_t id) {
314*6dbdd20aSAndroid Build Coastguard Worker PerfCounter ret;
315*6dbdd20aSAndroid Build Coastguard Worker ret.type = PerfCounter::Type::kTracepoint;
316*6dbdd20aSAndroid Build Coastguard Worker ret.tracepoint_name = std::move(tracepoint_name);
317*6dbdd20aSAndroid Build Coastguard Worker ret.tracepoint_filter = std::move(tracepoint_filter);
318*6dbdd20aSAndroid Build Coastguard Worker ret.name = std::move(name);
319*6dbdd20aSAndroid Build Coastguard Worker
320*6dbdd20aSAndroid Build Coastguard Worker ret.attr_type = PERF_TYPE_TRACEPOINT;
321*6dbdd20aSAndroid Build Coastguard Worker ret.attr_config = id;
322*6dbdd20aSAndroid Build Coastguard Worker return ret;
323*6dbdd20aSAndroid Build Coastguard Worker }
324*6dbdd20aSAndroid Build Coastguard Worker
325*6dbdd20aSAndroid Build Coastguard Worker // static
RawEvent(std::string name,uint32_t type,uint64_t config,uint64_t config1,uint64_t config2)326*6dbdd20aSAndroid Build Coastguard Worker PerfCounter PerfCounter::RawEvent(std::string name,
327*6dbdd20aSAndroid Build Coastguard Worker uint32_t type,
328*6dbdd20aSAndroid Build Coastguard Worker uint64_t config,
329*6dbdd20aSAndroid Build Coastguard Worker uint64_t config1,
330*6dbdd20aSAndroid Build Coastguard Worker uint64_t config2) {
331*6dbdd20aSAndroid Build Coastguard Worker PerfCounter ret;
332*6dbdd20aSAndroid Build Coastguard Worker ret.type = PerfCounter::Type::kRawEvent;
333*6dbdd20aSAndroid Build Coastguard Worker ret.name = std::move(name);
334*6dbdd20aSAndroid Build Coastguard Worker
335*6dbdd20aSAndroid Build Coastguard Worker ret.attr_type = type;
336*6dbdd20aSAndroid Build Coastguard Worker ret.attr_config = config;
337*6dbdd20aSAndroid Build Coastguard Worker ret.attr_config1 = config1;
338*6dbdd20aSAndroid Build Coastguard Worker ret.attr_config2 = config2;
339*6dbdd20aSAndroid Build Coastguard Worker return ret;
340*6dbdd20aSAndroid Build Coastguard Worker }
341*6dbdd20aSAndroid Build Coastguard Worker
342*6dbdd20aSAndroid Build Coastguard Worker // static
Create(const protos::gen::PerfEventConfig & pb_config,const DataSourceConfig & raw_ds_config,std::optional<ProcessSharding> process_sharding,tracepoint_id_fn_t tracepoint_id_lookup)343*6dbdd20aSAndroid Build Coastguard Worker std::optional<EventConfig> EventConfig::Create(
344*6dbdd20aSAndroid Build Coastguard Worker const protos::gen::PerfEventConfig& pb_config,
345*6dbdd20aSAndroid Build Coastguard Worker const DataSourceConfig& raw_ds_config,
346*6dbdd20aSAndroid Build Coastguard Worker std::optional<ProcessSharding> process_sharding,
347*6dbdd20aSAndroid Build Coastguard Worker tracepoint_id_fn_t tracepoint_id_lookup) {
348*6dbdd20aSAndroid Build Coastguard Worker // Timebase: sampling interval.
349*6dbdd20aSAndroid Build Coastguard Worker uint64_t sampling_frequency = 0;
350*6dbdd20aSAndroid Build Coastguard Worker uint64_t sampling_period = 0;
351*6dbdd20aSAndroid Build Coastguard Worker if (pb_config.timebase().period()) {
352*6dbdd20aSAndroid Build Coastguard Worker sampling_period = pb_config.timebase().period();
353*6dbdd20aSAndroid Build Coastguard Worker } else if (pb_config.timebase().frequency()) {
354*6dbdd20aSAndroid Build Coastguard Worker sampling_frequency = pb_config.timebase().frequency();
355*6dbdd20aSAndroid Build Coastguard Worker } else if (pb_config.sampling_frequency()) { // backwards compatibility
356*6dbdd20aSAndroid Build Coastguard Worker sampling_frequency = pb_config.sampling_frequency();
357*6dbdd20aSAndroid Build Coastguard Worker } else {
358*6dbdd20aSAndroid Build Coastguard Worker sampling_frequency = kDefaultSamplingFrequencyHz;
359*6dbdd20aSAndroid Build Coastguard Worker }
360*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DCHECK(sampling_period && !sampling_frequency ||
361*6dbdd20aSAndroid Build Coastguard Worker !sampling_period && sampling_frequency);
362*6dbdd20aSAndroid Build Coastguard Worker
363*6dbdd20aSAndroid Build Coastguard Worker // Leader event. Default: CPU timer.
364*6dbdd20aSAndroid Build Coastguard Worker PerfCounter timebase_event;
365*6dbdd20aSAndroid Build Coastguard Worker std::string timebase_name = pb_config.timebase().name();
366*6dbdd20aSAndroid Build Coastguard Worker
367*6dbdd20aSAndroid Build Coastguard Worker // Build timebase.
368*6dbdd20aSAndroid Build Coastguard Worker auto maybe_perf_counter = MakePerfCounter(tracepoint_id_lookup, timebase_name,
369*6dbdd20aSAndroid Build Coastguard Worker pb_config.timebase());
370*6dbdd20aSAndroid Build Coastguard Worker if (!maybe_perf_counter) {
371*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
372*6dbdd20aSAndroid Build Coastguard Worker }
373*6dbdd20aSAndroid Build Coastguard Worker timebase_event = std::move(*maybe_perf_counter);
374*6dbdd20aSAndroid Build Coastguard Worker
375*6dbdd20aSAndroid Build Coastguard Worker // Build the followers.
376*6dbdd20aSAndroid Build Coastguard Worker std::vector<PerfCounter> followers;
377*6dbdd20aSAndroid Build Coastguard Worker for (const auto& event : pb_config.followers()) {
378*6dbdd20aSAndroid Build Coastguard Worker const auto& name = event.name();
379*6dbdd20aSAndroid Build Coastguard Worker auto maybe_follower_counter =
380*6dbdd20aSAndroid Build Coastguard Worker MakePerfCounter(tracepoint_id_lookup, name, event);
381*6dbdd20aSAndroid Build Coastguard Worker if (!maybe_follower_counter) {
382*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
383*6dbdd20aSAndroid Build Coastguard Worker }
384*6dbdd20aSAndroid Build Coastguard Worker followers.push_back(std::move(*maybe_follower_counter));
385*6dbdd20aSAndroid Build Coastguard Worker }
386*6dbdd20aSAndroid Build Coastguard Worker
387*6dbdd20aSAndroid Build Coastguard Worker // Callstack sampling.
388*6dbdd20aSAndroid Build Coastguard Worker bool kernel_frames = false;
389*6dbdd20aSAndroid Build Coastguard Worker // Disable user_frames by default.
390*6dbdd20aSAndroid Build Coastguard Worker auto unwind_mode = protos::gen::PerfEventConfig::UNWIND_SKIP;
391*6dbdd20aSAndroid Build Coastguard Worker
392*6dbdd20aSAndroid Build Coastguard Worker TargetFilter target_filter;
393*6dbdd20aSAndroid Build Coastguard Worker bool legacy_config = pb_config.all_cpus(); // all_cpus was mandatory before
394*6dbdd20aSAndroid Build Coastguard Worker if (pb_config.has_callstack_sampling() || legacy_config) {
395*6dbdd20aSAndroid Build Coastguard Worker // Userspace callstacks.
396*6dbdd20aSAndroid Build Coastguard Worker unwind_mode = pb_config.callstack_sampling().user_frames();
397*6dbdd20aSAndroid Build Coastguard Worker if (!IsSupportedUnwindMode(unwind_mode)) {
398*6dbdd20aSAndroid Build Coastguard Worker // enum value from the future that we don't yet know, refuse the config
399*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
400*6dbdd20aSAndroid Build Coastguard Worker }
401*6dbdd20aSAndroid Build Coastguard Worker
402*6dbdd20aSAndroid Build Coastguard Worker // Process scoping. Sharding parameter is supplied from outside as it is
403*6dbdd20aSAndroid Build Coastguard Worker // shared by all data sources within a tracing session.
404*6dbdd20aSAndroid Build Coastguard Worker target_filter =
405*6dbdd20aSAndroid Build Coastguard Worker pb_config.callstack_sampling().has_scope()
406*6dbdd20aSAndroid Build Coastguard Worker ? ParseTargetFilter(pb_config.callstack_sampling().scope(),
407*6dbdd20aSAndroid Build Coastguard Worker process_sharding)
408*6dbdd20aSAndroid Build Coastguard Worker : ParseTargetFilter(pb_config,
409*6dbdd20aSAndroid Build Coastguard Worker process_sharding); // backwards compatibility
410*6dbdd20aSAndroid Build Coastguard Worker
411*6dbdd20aSAndroid Build Coastguard Worker // Kernel callstacks.
412*6dbdd20aSAndroid Build Coastguard Worker kernel_frames = pb_config.callstack_sampling().kernel_frames() ||
413*6dbdd20aSAndroid Build Coastguard Worker pb_config.kernel_frames();
414*6dbdd20aSAndroid Build Coastguard Worker }
415*6dbdd20aSAndroid Build Coastguard Worker
416*6dbdd20aSAndroid Build Coastguard Worker // Ring buffer options.
417*6dbdd20aSAndroid Build Coastguard Worker std::optional<uint32_t> ring_buffer_pages =
418*6dbdd20aSAndroid Build Coastguard Worker ChooseActualRingBufferPages(pb_config.ring_buffer_pages());
419*6dbdd20aSAndroid Build Coastguard Worker if (!ring_buffer_pages.has_value())
420*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
421*6dbdd20aSAndroid Build Coastguard Worker
422*6dbdd20aSAndroid Build Coastguard Worker uint32_t read_tick_period_ms = pb_config.ring_buffer_read_period_ms()
423*6dbdd20aSAndroid Build Coastguard Worker ? pb_config.ring_buffer_read_period_ms()
424*6dbdd20aSAndroid Build Coastguard Worker : kDefaultReadTickPeriodMs;
425*6dbdd20aSAndroid Build Coastguard Worker
426*6dbdd20aSAndroid Build Coastguard Worker // Calculate a rough upper limit for the amount of samples the producer
427*6dbdd20aSAndroid Build Coastguard Worker // should read per read tick, as a safeguard against getting stuck chasing the
428*6dbdd20aSAndroid Build Coastguard Worker // ring buffer head indefinitely.
429*6dbdd20aSAndroid Build Coastguard Worker uint64_t samples_per_tick_limit = 0;
430*6dbdd20aSAndroid Build Coastguard Worker if (sampling_frequency) {
431*6dbdd20aSAndroid Build Coastguard Worker // expected = rate * period, with a conversion of period from ms to s:
432*6dbdd20aSAndroid Build Coastguard Worker uint64_t expected_samples_per_tick =
433*6dbdd20aSAndroid Build Coastguard Worker 1 + (sampling_frequency * read_tick_period_ms) / 1000;
434*6dbdd20aSAndroid Build Coastguard Worker // Double the limit to account of actual sample rate uncertainties, as
435*6dbdd20aSAndroid Build Coastguard Worker // well as any other factors:
436*6dbdd20aSAndroid Build Coastguard Worker samples_per_tick_limit = 2 * expected_samples_per_tick;
437*6dbdd20aSAndroid Build Coastguard Worker } else { // sampling_period
438*6dbdd20aSAndroid Build Coastguard Worker // We don't know the sample rate that a fixed period would cause, but we can
439*6dbdd20aSAndroid Build Coastguard Worker // still estimate how many samples will fit in one pass of the ring buffer
440*6dbdd20aSAndroid Build Coastguard Worker // (with the assumption that we don't want to read more than one buffer's
441*6dbdd20aSAndroid Build Coastguard Worker // capacity within a tick).
442*6dbdd20aSAndroid Build Coastguard Worker // TODO(rsavitski): for now, make an extremely conservative guess of an 8
443*6dbdd20aSAndroid Build Coastguard Worker // byte sample (stack sampling samples can be up to 64KB). This is most
444*6dbdd20aSAndroid Build Coastguard Worker // likely as good as no limit in practice.
445*6dbdd20aSAndroid Build Coastguard Worker samples_per_tick_limit = *ring_buffer_pages * (base::GetSysPageSize() / 8);
446*6dbdd20aSAndroid Build Coastguard Worker }
447*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DLOG("Capping samples (not records) per tick to [%" PRIu64 "]",
448*6dbdd20aSAndroid Build Coastguard Worker samples_per_tick_limit);
449*6dbdd20aSAndroid Build Coastguard Worker if (samples_per_tick_limit == 0)
450*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
451*6dbdd20aSAndroid Build Coastguard Worker
452*6dbdd20aSAndroid Build Coastguard Worker // Optional footprint controls.
453*6dbdd20aSAndroid Build Coastguard Worker uint64_t max_enqueued_footprint_bytes =
454*6dbdd20aSAndroid Build Coastguard Worker pb_config.max_enqueued_footprint_kb() * 1024;
455*6dbdd20aSAndroid Build Coastguard Worker
456*6dbdd20aSAndroid Build Coastguard Worker // Android-specific options.
457*6dbdd20aSAndroid Build Coastguard Worker uint32_t remote_descriptor_timeout_ms =
458*6dbdd20aSAndroid Build Coastguard Worker pb_config.remote_descriptor_timeout_ms()
459*6dbdd20aSAndroid Build Coastguard Worker ? pb_config.remote_descriptor_timeout_ms()
460*6dbdd20aSAndroid Build Coastguard Worker : kDefaultRemoteDescriptorTimeoutMs;
461*6dbdd20aSAndroid Build Coastguard Worker
462*6dbdd20aSAndroid Build Coastguard Worker // Build the underlying syscall config struct.
463*6dbdd20aSAndroid Build Coastguard Worker perf_event_attr pe = {};
464*6dbdd20aSAndroid Build Coastguard Worker pe.size = sizeof(perf_event_attr);
465*6dbdd20aSAndroid Build Coastguard Worker pe.disabled = 1; // will be activated via ioctl
466*6dbdd20aSAndroid Build Coastguard Worker
467*6dbdd20aSAndroid Build Coastguard Worker // Sampling timebase.
468*6dbdd20aSAndroid Build Coastguard Worker pe.type = timebase_event.attr_type;
469*6dbdd20aSAndroid Build Coastguard Worker pe.config = timebase_event.attr_config;
470*6dbdd20aSAndroid Build Coastguard Worker pe.config1 = timebase_event.attr_config1;
471*6dbdd20aSAndroid Build Coastguard Worker pe.config2 = timebase_event.attr_config2;
472*6dbdd20aSAndroid Build Coastguard Worker if (sampling_frequency) {
473*6dbdd20aSAndroid Build Coastguard Worker pe.freq = true;
474*6dbdd20aSAndroid Build Coastguard Worker pe.sample_freq = sampling_frequency;
475*6dbdd20aSAndroid Build Coastguard Worker } else {
476*6dbdd20aSAndroid Build Coastguard Worker pe.sample_period = sampling_period;
477*6dbdd20aSAndroid Build Coastguard Worker }
478*6dbdd20aSAndroid Build Coastguard Worker
479*6dbdd20aSAndroid Build Coastguard Worker // What the samples will contain.
480*6dbdd20aSAndroid Build Coastguard Worker pe.sample_type = PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_READ;
481*6dbdd20aSAndroid Build Coastguard Worker // PERF_SAMPLE_TIME:
482*6dbdd20aSAndroid Build Coastguard Worker pe.clockid = ToClockId(pb_config.timebase().timestamp_clock());
483*6dbdd20aSAndroid Build Coastguard Worker pe.use_clockid = true;
484*6dbdd20aSAndroid Build Coastguard Worker
485*6dbdd20aSAndroid Build Coastguard Worker if (IsUserFramesEnabled(unwind_mode)) {
486*6dbdd20aSAndroid Build Coastguard Worker pe.sample_type |= PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER;
487*6dbdd20aSAndroid Build Coastguard Worker // PERF_SAMPLE_STACK_USER:
488*6dbdd20aSAndroid Build Coastguard Worker // Needs to be < ((u16)(~0u)), and have bottom 8 bits clear.
489*6dbdd20aSAndroid Build Coastguard Worker // Note that the kernel still needs to make space for the other parts of the
490*6dbdd20aSAndroid Build Coastguard Worker // sample (up to the max record size of 64k), so the effective maximum
491*6dbdd20aSAndroid Build Coastguard Worker // can be lower than this.
492*6dbdd20aSAndroid Build Coastguard Worker pe.sample_stack_user = (1u << 16) - 256;
493*6dbdd20aSAndroid Build Coastguard Worker // PERF_SAMPLE_REGS_USER:
494*6dbdd20aSAndroid Build Coastguard Worker pe.sample_regs_user =
495*6dbdd20aSAndroid Build Coastguard Worker PerfUserRegsMaskForArch(unwindstack::Regs::CurrentArch());
496*6dbdd20aSAndroid Build Coastguard Worker }
497*6dbdd20aSAndroid Build Coastguard Worker if (kernel_frames) {
498*6dbdd20aSAndroid Build Coastguard Worker pe.sample_type |= PERF_SAMPLE_CALLCHAIN;
499*6dbdd20aSAndroid Build Coastguard Worker pe.exclude_callchain_user = true;
500*6dbdd20aSAndroid Build Coastguard Worker }
501*6dbdd20aSAndroid Build Coastguard Worker
502*6dbdd20aSAndroid Build Coastguard Worker // Build the events associated with the timebase event (pe).
503*6dbdd20aSAndroid Build Coastguard Worker // The timebase event drives the capture with its frequency or period
504*6dbdd20aSAndroid Build Coastguard Worker // parameter. When linux captures the timebase event it also reads and report
505*6dbdd20aSAndroid Build Coastguard Worker // the values of associated events.
506*6dbdd20aSAndroid Build Coastguard Worker std::vector<perf_event_attr> pe_followers;
507*6dbdd20aSAndroid Build Coastguard Worker if (!followers.empty()) {
508*6dbdd20aSAndroid Build Coastguard Worker pe.read_format = PERF_FORMAT_GROUP;
509*6dbdd20aSAndroid Build Coastguard Worker pe_followers.reserve(followers.size());
510*6dbdd20aSAndroid Build Coastguard Worker }
511*6dbdd20aSAndroid Build Coastguard Worker
512*6dbdd20aSAndroid Build Coastguard Worker for (const auto& e : followers) {
513*6dbdd20aSAndroid Build Coastguard Worker perf_event_attr pe_follower = {};
514*6dbdd20aSAndroid Build Coastguard Worker pe_follower.size = sizeof(perf_event_attr);
515*6dbdd20aSAndroid Build Coastguard Worker pe_follower.disabled = 0; // activated when the timebase is activated
516*6dbdd20aSAndroid Build Coastguard Worker pe_follower.type = e.attr_type;
517*6dbdd20aSAndroid Build Coastguard Worker pe_follower.config = e.attr_config;
518*6dbdd20aSAndroid Build Coastguard Worker pe_follower.config1 = e.attr_config1;
519*6dbdd20aSAndroid Build Coastguard Worker pe_follower.config2 = e.attr_config2;
520*6dbdd20aSAndroid Build Coastguard Worker pe_follower.sample_type =
521*6dbdd20aSAndroid Build Coastguard Worker PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_READ;
522*6dbdd20aSAndroid Build Coastguard Worker pe_follower.freq = 0;
523*6dbdd20aSAndroid Build Coastguard Worker pe_follower.sample_period = 0;
524*6dbdd20aSAndroid Build Coastguard Worker pe_follower.clockid = ToClockId(pb_config.timebase().timestamp_clock());
525*6dbdd20aSAndroid Build Coastguard Worker pe_follower.use_clockid = true;
526*6dbdd20aSAndroid Build Coastguard Worker
527*6dbdd20aSAndroid Build Coastguard Worker pe_followers.push_back(pe_follower);
528*6dbdd20aSAndroid Build Coastguard Worker }
529*6dbdd20aSAndroid Build Coastguard Worker
530*6dbdd20aSAndroid Build Coastguard Worker return EventConfig(
531*6dbdd20aSAndroid Build Coastguard Worker raw_ds_config, pe, std::move(pe_followers), timebase_event, followers,
532*6dbdd20aSAndroid Build Coastguard Worker kernel_frames, unwind_mode, std::move(target_filter),
533*6dbdd20aSAndroid Build Coastguard Worker ring_buffer_pages.value(), read_tick_period_ms, samples_per_tick_limit,
534*6dbdd20aSAndroid Build Coastguard Worker remote_descriptor_timeout_ms, pb_config.unwind_state_clear_period_ms(),
535*6dbdd20aSAndroid Build Coastguard Worker max_enqueued_footprint_bytes, pb_config.target_installed_by());
536*6dbdd20aSAndroid Build Coastguard Worker }
537*6dbdd20aSAndroid Build Coastguard Worker
538*6dbdd20aSAndroid Build Coastguard Worker // static
IsUserFramesEnabled(const protos::gen::PerfEventConfig::UnwindMode unwind_mode)539*6dbdd20aSAndroid Build Coastguard Worker bool EventConfig::IsUserFramesEnabled(
540*6dbdd20aSAndroid Build Coastguard Worker const protos::gen::PerfEventConfig::UnwindMode unwind_mode) {
541*6dbdd20aSAndroid Build Coastguard Worker using protos::gen::PerfEventConfig;
542*6dbdd20aSAndroid Build Coastguard Worker switch (unwind_mode) {
543*6dbdd20aSAndroid Build Coastguard Worker case PerfEventConfig::UNWIND_UNKNOWN:
544*6dbdd20aSAndroid Build Coastguard Worker // default to true, both for backwards compatibility and because it's
545*6dbdd20aSAndroid Build Coastguard Worker // almost always what the user wants.
546*6dbdd20aSAndroid Build Coastguard Worker case PerfEventConfig::UNWIND_DWARF:
547*6dbdd20aSAndroid Build Coastguard Worker case PerfEventConfig::UNWIND_FRAME_POINTER:
548*6dbdd20aSAndroid Build Coastguard Worker return true;
549*6dbdd20aSAndroid Build Coastguard Worker case PerfEventConfig::UNWIND_SKIP:
550*6dbdd20aSAndroid Build Coastguard Worker return false;
551*6dbdd20aSAndroid Build Coastguard Worker }
552*6dbdd20aSAndroid Build Coastguard Worker }
553*6dbdd20aSAndroid Build Coastguard Worker
EventConfig(const DataSourceConfig & raw_ds_config,const perf_event_attr & pe_timebase,std::vector<perf_event_attr> pe_followers,const PerfCounter & timebase_event,std::vector<PerfCounter> follower_events,bool kernel_frames,protos::gen::PerfEventConfig::UnwindMode unwind_mode,TargetFilter target_filter,uint32_t ring_buffer_pages,uint32_t read_tick_period_ms,uint64_t samples_per_tick_limit,uint32_t remote_descriptor_timeout_ms,uint32_t unwind_state_clear_period_ms,uint64_t max_enqueued_footprint_bytes,std::vector<std::string> target_installed_by)554*6dbdd20aSAndroid Build Coastguard Worker EventConfig::EventConfig(const DataSourceConfig& raw_ds_config,
555*6dbdd20aSAndroid Build Coastguard Worker const perf_event_attr& pe_timebase,
556*6dbdd20aSAndroid Build Coastguard Worker std::vector<perf_event_attr> pe_followers,
557*6dbdd20aSAndroid Build Coastguard Worker const PerfCounter& timebase_event,
558*6dbdd20aSAndroid Build Coastguard Worker std::vector<PerfCounter> follower_events,
559*6dbdd20aSAndroid Build Coastguard Worker bool kernel_frames,
560*6dbdd20aSAndroid Build Coastguard Worker protos::gen::PerfEventConfig::UnwindMode unwind_mode,
561*6dbdd20aSAndroid Build Coastguard Worker TargetFilter target_filter,
562*6dbdd20aSAndroid Build Coastguard Worker uint32_t ring_buffer_pages,
563*6dbdd20aSAndroid Build Coastguard Worker uint32_t read_tick_period_ms,
564*6dbdd20aSAndroid Build Coastguard Worker uint64_t samples_per_tick_limit,
565*6dbdd20aSAndroid Build Coastguard Worker uint32_t remote_descriptor_timeout_ms,
566*6dbdd20aSAndroid Build Coastguard Worker uint32_t unwind_state_clear_period_ms,
567*6dbdd20aSAndroid Build Coastguard Worker uint64_t max_enqueued_footprint_bytes,
568*6dbdd20aSAndroid Build Coastguard Worker std::vector<std::string> target_installed_by)
569*6dbdd20aSAndroid Build Coastguard Worker : perf_event_attr_(pe_timebase),
570*6dbdd20aSAndroid Build Coastguard Worker perf_event_followers_(std::move(pe_followers)),
571*6dbdd20aSAndroid Build Coastguard Worker timebase_event_(timebase_event),
572*6dbdd20aSAndroid Build Coastguard Worker follower_events_(std::move(follower_events)),
573*6dbdd20aSAndroid Build Coastguard Worker kernel_frames_(kernel_frames),
574*6dbdd20aSAndroid Build Coastguard Worker unwind_mode_(unwind_mode),
575*6dbdd20aSAndroid Build Coastguard Worker target_filter_(std::move(target_filter)),
576*6dbdd20aSAndroid Build Coastguard Worker ring_buffer_pages_(ring_buffer_pages),
577*6dbdd20aSAndroid Build Coastguard Worker read_tick_period_ms_(read_tick_period_ms),
578*6dbdd20aSAndroid Build Coastguard Worker samples_per_tick_limit_(samples_per_tick_limit),
579*6dbdd20aSAndroid Build Coastguard Worker remote_descriptor_timeout_ms_(remote_descriptor_timeout_ms),
580*6dbdd20aSAndroid Build Coastguard Worker unwind_state_clear_period_ms_(unwind_state_clear_period_ms),
581*6dbdd20aSAndroid Build Coastguard Worker max_enqueued_footprint_bytes_(max_enqueued_footprint_bytes),
582*6dbdd20aSAndroid Build Coastguard Worker target_installed_by_(std::move(target_installed_by)),
583*6dbdd20aSAndroid Build Coastguard Worker raw_ds_config_(raw_ds_config) /* full copy */ {}
584*6dbdd20aSAndroid Build Coastguard Worker
585*6dbdd20aSAndroid Build Coastguard Worker } // namespace profiling
586*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto
587