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 <cinttypes> 21 #include <functional> 22 #include <string> 23 #include <vector> 24 25 #include <linux/perf_event.h> 26 #include <stdint.h> 27 #include <sys/types.h> 28 #include <optional> 29 30 #include "perfetto/base/flat_set.h" 31 #include "perfetto/tracing/core/data_source_config.h" 32 33 #include "protos/perfetto/common/perf_events.gen.h" 34 #include "protos/perfetto/config/profiling/perf_event_config.gen.h" 35 36 namespace perfetto { 37 namespace protos { 38 namespace gen { 39 class PerfEventConfig; 40 } // namespace gen 41 } // namespace protos 42 43 namespace profiling { 44 45 // Callstack sampling parameter for unwinding only a fraction of seen processes 46 // (without enumerating them in the config). 47 struct ProcessSharding { 48 uint32_t shard_count = 0; 49 uint32_t chosen_shard = 0; 50 }; 51 52 // Parsed allow/deny-list for filtering samples. 53 // An empty allow-list means that all targets are allowed unless explicitly 54 // denied. 55 struct TargetFilter { 56 std::vector<std::string> cmdlines; 57 std::vector<std::string> exclude_cmdlines; 58 base::FlatSet<pid_t> pids; 59 base::FlatSet<pid_t> exclude_pids; 60 std::optional<ProcessSharding> process_sharding; 61 uint32_t additional_cmdline_count = 0; 62 }; 63 64 // Describes a perf event for two purposes: 65 // * encoding the event in the perf_event_open syscall 66 // * echoing the counter's config in the trace packet defaults, so that the 67 // parser can tell which datastream belongs to which counter. 68 // Note: It's slightly odd to decode & pass around values we don't use outside 69 // of reencoding back into a defaults proto. One option would be to carry the 70 // Timebase proto, but this won't fit with the eventual support of multiple 71 // counters, as at the proto level it'll be a distinct message from Timebase. 72 struct PerfCounter { 73 enum class Type { kBuiltinCounter, kTracepoint, kRawEvent }; 74 75 Type type = Type::kBuiltinCounter; 76 77 // Optional config-supplied name for the counter, to identify it during 78 // trace parsing, does not affect the syscall. 79 std::string name; 80 81 // valid if kBuiltinCounter 82 protos::gen::PerfEvents::Counter counter = 83 protos::gen::PerfEvents::PerfEvents::UNKNOWN_COUNTER; 84 // valid if kTracepoint. Example: "sched:sched_switch". 85 std::string tracepoint_name; 86 // valid if kTracepoint 87 std::string tracepoint_filter; 88 89 // sycall-level description of the event (perf_event_attr): 90 uint32_t attr_type = 0; 91 uint64_t attr_config = 0; 92 uint64_t attr_config1 = 0; // optional extension 93 uint64_t attr_config2 = 0; // optional extension 94 event_typePerfCounter95 Type event_type() const { return type; } 96 97 static PerfCounter BuiltinCounter(std::string name, 98 protos::gen::PerfEvents::Counter counter, 99 uint32_t type, 100 uint64_t config); 101 102 static PerfCounter Tracepoint(std::string name, 103 std::string tracepoint_name, 104 std::string tracepoint_filter, 105 uint64_t id); 106 107 static PerfCounter RawEvent(std::string name, 108 uint32_t type, 109 uint64_t config, 110 uint64_t config1, 111 uint64_t config2); 112 }; 113 114 // Describes a single profiling configuration. Bridges the gap between the data 115 // source config proto, and the raw "perf_event_attr" structs to pass to the 116 // perf_event_open syscall. 117 class EventConfig { 118 public: 119 using tracepoint_id_fn_t = 120 std::function<uint32_t(const std::string&, const std::string&)>; 121 122 static std::optional<EventConfig> Create( 123 const protos::gen::PerfEventConfig& pb_config, 124 const DataSourceConfig& raw_ds_config, 125 std::optional<ProcessSharding> process_sharding, 126 tracepoint_id_fn_t tracepoint_id_lookup); 127 ring_buffer_pages()128 uint32_t ring_buffer_pages() const { return ring_buffer_pages_; } read_tick_period_ms()129 uint32_t read_tick_period_ms() const { return read_tick_period_ms_; } samples_per_tick_limit()130 uint64_t samples_per_tick_limit() const { return samples_per_tick_limit_; } remote_descriptor_timeout_ms()131 uint32_t remote_descriptor_timeout_ms() const { 132 return remote_descriptor_timeout_ms_; 133 } unwind_state_clear_period_ms()134 uint32_t unwind_state_clear_period_ms() const { 135 return unwind_state_clear_period_ms_; 136 } max_enqueued_footprint_bytes()137 uint64_t max_enqueued_footprint_bytes() const { 138 return max_enqueued_footprint_bytes_; 139 } sample_callstacks()140 bool sample_callstacks() const { return user_frames() || kernel_frames_; } user_frames()141 bool user_frames() const { return IsUserFramesEnabled(unwind_mode_); } kernel_frames()142 bool kernel_frames() const { return kernel_frames_; } unwind_mode()143 protos::gen::PerfEventConfig::UnwindMode unwind_mode() const { 144 return unwind_mode_; 145 } filter()146 const TargetFilter& filter() const { return target_filter_; } perf_attr()147 perf_event_attr* perf_attr() const { 148 return const_cast<perf_event_attr*>(&perf_event_attr_); 149 } perf_attr_followers()150 const std::vector<perf_event_attr>& perf_attr_followers() const { 151 return perf_event_followers_; 152 } timebase_event()153 const PerfCounter& timebase_event() const { return timebase_event_; } 154 follower_events()155 const std::vector<PerfCounter>& follower_events() const { 156 return follower_events_; 157 } 158 target_installed_by()159 const std::vector<std::string>& target_installed_by() const { 160 return target_installed_by_; 161 } raw_ds_config()162 const DataSourceConfig& raw_ds_config() const { return raw_ds_config_; } 163 164 private: 165 static bool IsUserFramesEnabled( 166 const protos::gen::PerfEventConfig::UnwindMode unwind_mode); 167 168 EventConfig(const DataSourceConfig& raw_ds_config, 169 const perf_event_attr& pe_timebase, 170 std::vector<perf_event_attr> pe_followers, 171 const PerfCounter& timebase_event, 172 std::vector<PerfCounter> follower_events, 173 bool kernel_frames, 174 protos::gen::PerfEventConfig::UnwindMode unwind_mode, 175 TargetFilter target_filter, 176 uint32_t ring_buffer_pages, 177 uint32_t read_tick_period_ms, 178 uint64_t samples_per_tick_limit, 179 uint32_t remote_descriptor_timeout_ms, 180 uint32_t unwind_state_clear_period_ms, 181 uint64_t max_enqueued_footprint_bytes, 182 std::vector<std::string> target_installed_by); 183 184 // Parameter struct for the timebase perf_event_open syscall. 185 perf_event_attr perf_event_attr_ = {}; 186 187 std::vector<perf_event_attr> perf_event_followers_ = {}; 188 189 // Timebase event, which is already described by |perf_event_attr_|. But this 190 // additionally carries a tracepoint filter if that needs to be set via an 191 // ioctl after creating the event. 192 const PerfCounter timebase_event_; 193 194 // Timebase event, which are already described by |perf_event_followers_|. 195 std::vector<PerfCounter> follower_events_; 196 197 // If true, include kernel frames in sampled callstacks. 198 const bool kernel_frames_; 199 200 // Userspace unwinding mode. 201 const protos::gen::PerfEventConfig::UnwindMode unwind_mode_; 202 203 // Parsed allow/deny-list for filtering samples. 204 const TargetFilter target_filter_; 205 206 // Size (in 4k pages) of each per-cpu ring buffer shared with the kernel. 207 // Must be a power of two. 208 const uint32_t ring_buffer_pages_; 209 210 // How often the ring buffers should be read. 211 const uint32_t read_tick_period_ms_; 212 213 // Guardrail for the amount of samples a given read attempt will extract from 214 // *each* per-cpu buffer. 215 const uint64_t samples_per_tick_limit_; 216 217 // Timeout for proc-fd lookup. 218 const uint32_t remote_descriptor_timeout_ms_; 219 220 // Optional period for clearing cached unwinder state. Skipped if zero. 221 const uint32_t unwind_state_clear_period_ms_; 222 223 const uint64_t max_enqueued_footprint_bytes_; 224 225 // Only profile target if it was installed by one of the packages given. 226 // Special values are: 227 // * "@system": installed on the system partition 228 // * "@product": installed on the product partition 229 // * "@null": sideloaded 230 const std::vector<std::string> target_installed_by_; 231 232 // The raw data source config, as a pbzero-generated C++ class. 233 const DataSourceConfig raw_ds_config_; 234 }; 235 236 } // namespace profiling 237 } // namespace perfetto 238 239 #endif // SRC_PROFILING_PERF_EVENT_CONFIG_H_ 240