1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SRC_PROFILING_PERF_EVENT_CONFIG_H_
18 #define SRC_PROFILING_PERF_EVENT_CONFIG_H_
19 
20 #include <functional>
21 #include <string>
22 #include <vector>
23 
24 #include <inttypes.h>
25 #include <linux/perf_event.h>
26 #include <stdint.h>
27 #include <sys/types.h>
28 
29 #include "perfetto/base/flat_set.h"
30 #include "perfetto/ext/base/optional.h"
31 #include "perfetto/tracing/core/data_source_config.h"
32 
33 #include "protos/perfetto/common/perf_events.gen.h"
34 
35 namespace perfetto {
36 namespace protos {
37 namespace gen {
38 class PerfEventConfig;
39 }  // namespace gen
40 }  // namespace protos
41 
42 namespace profiling {
43 
44 // Parsed allow/deny-list for filtering samples.
45 // An empty filter set means that all targets are allowed.
46 struct TargetFilter {
47   base::FlatSet<std::string> cmdlines;
48   base::FlatSet<std::string> exclude_cmdlines;
49   base::FlatSet<pid_t> pids;
50   base::FlatSet<pid_t> exclude_pids;
51   uint32_t additional_cmdline_count = 0;
52 };
53 
54 struct PerfCounter {
55   // Either a predefined counter, or a tracepoint:
56   protos::gen::PerfEvents::Counter counter =
57       protos::gen::PerfEvents::PerfEvents::UNKNOWN_COUNTER;
58   protos::gen::PerfEvents::Tracepoint tracepoint;
59 
60   // sycall-level description of the event:
61   uint32_t type = 0;    // perf_event_attr.type
62   uint32_t config = 0;  // perf_event_attr.config
63 
is_counterPerfCounter64   bool is_counter() const {
65     return counter != protos::gen::PerfEvents::PerfEvents::UNKNOWN_COUNTER;
66   }
is_tracepointPerfCounter67   bool is_tracepoint() const { return type == PERF_TYPE_TRACEPOINT; }
68 
69   static PerfCounter Counter(protos::gen::PerfEvents::Counter counter,
70                              uint32_t type,
71                              uint32_t config);
72 
73   static PerfCounter Tracepoint(protos::gen::PerfEvents::Tracepoint tracepoint,
74                                 uint32_t id);
75 };
76 
77 // Describes a single profiling configuration. Bridges the gap between the data
78 // source config proto, and the raw "perf_event_attr" structs to pass to the
79 // perf_event_open syscall.
80 class EventConfig {
81  public:
82   using tracepoint_id_fn_t =
83       std::function<uint32_t(const std::string&, const std::string&)>;
84 
85   static base::Optional<EventConfig> Create(
86       const DataSourceConfig& ds_config,
87       tracepoint_id_fn_t tracepoint_id_lookup =
88           [](const std::string&, const std::string&) { return 0; });
89 
90   static base::Optional<EventConfig> Create(
91       const protos::gen::PerfEventConfig& pb_config,
92       const DataSourceConfig& raw_ds_config,
93       tracepoint_id_fn_t tracepoint_id_lookup);
94 
ring_buffer_pages()95   uint32_t ring_buffer_pages() const { return ring_buffer_pages_; }
read_tick_period_ms()96   uint32_t read_tick_period_ms() const { return read_tick_period_ms_; }
samples_per_tick_limit()97   uint64_t samples_per_tick_limit() const { return samples_per_tick_limit_; }
remote_descriptor_timeout_ms()98   uint32_t remote_descriptor_timeout_ms() const {
99     return remote_descriptor_timeout_ms_;
100   }
unwind_state_clear_period_ms()101   uint32_t unwind_state_clear_period_ms() const {
102     return unwind_state_clear_period_ms_;
103   }
max_enqueued_footprint_bytes()104   uint64_t max_enqueued_footprint_bytes() const {
105     return max_enqueued_footprint_bytes_;
106   }
sample_callstacks()107   bool sample_callstacks() const { return sample_callstacks_; }
filter()108   const TargetFilter& filter() const { return target_filter_; }
kernel_frames()109   bool kernel_frames() const { return kernel_frames_; }
perf_attr()110   perf_event_attr* perf_attr() const {
111     return const_cast<perf_event_attr*>(&perf_event_attr_);
112   }
timebase_event()113   const PerfCounter& timebase_event() const { return timebase_event_; }
target_installed_by()114   const std::vector<std::string>& target_installed_by() const {
115     return target_installed_by_;
116   }
raw_ds_config()117   const DataSourceConfig& raw_ds_config() const { return raw_ds_config_; }
118 
119  private:
120   EventConfig(const DataSourceConfig& raw_ds_config,
121               const perf_event_attr& pe,
122               const PerfCounter& timebase_event,
123               bool sample_callstacks,
124               TargetFilter target_filter,
125               bool kernel_frames,
126               uint32_t ring_buffer_pages,
127               uint32_t read_tick_period_ms,
128               uint64_t samples_per_tick_limit,
129               uint32_t remote_descriptor_timeout_ms,
130               uint32_t unwind_state_clear_period_ms,
131               uint64_t max_enqueued_footprint_bytes,
132               std::vector<std::string> target_installed_by);
133 
134   // Parameter struct for the leader (timebase) perf_event_open syscall.
135   perf_event_attr perf_event_attr_ = {};
136 
137   // Leader event, which is already described by |perf_event_attr_|. But this
138   // additionally carries a tracepoint filter if that needs to be set via an
139   // ioctl after creating the event.
140   const PerfCounter timebase_event_;
141 
142   // TODO(rsavitski): consider adding an Optional<CallstackSampling> that
143   // contains the kernel_frames_ and target_filter, once the complexity warrants
144   // it.
145   const bool sample_callstacks_;
146 
147   // Parsed allow/deny-list for filtering samples.
148   const TargetFilter target_filter_;
149 
150   // If true, include kernel frames in the callstacks.
151   const bool kernel_frames_;
152 
153   // Size (in 4k pages) of each per-cpu ring buffer shared with the kernel.
154   // Must be a power of two.
155   const uint32_t ring_buffer_pages_;
156 
157   // How often the ring buffers should be read.
158   const uint32_t read_tick_period_ms_;
159 
160   // Guardrail for the amount of samples a given read attempt will extract from
161   // *each* per-cpu buffer.
162   const uint64_t samples_per_tick_limit_;
163 
164   // Timeout for proc-fd lookup.
165   const uint32_t remote_descriptor_timeout_ms_;
166 
167   // Optional period for clearing cached unwinder state. Skipped if zero.
168   const uint32_t unwind_state_clear_period_ms_;
169 
170   const uint64_t max_enqueued_footprint_bytes_;
171 
172   // Only profile target if it was installed by one of the packages given.
173   // Special values are:
174   // * @system: installed on the system partition
175   // * @product: installed on the product partition
176   // * @null: sideloaded
177   const std::vector<std::string> target_installed_by_;
178 
179   // The raw data source config, as a pbzero-generated C++ class.
180   const DataSourceConfig raw_ds_config_;
181 };
182 
183 }  // namespace profiling
184 }  // namespace perfetto
185 
186 #endif  // SRC_PROFILING_PERF_EVENT_CONFIG_H_
187