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 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 std::vector<std::string> cmdlines; 48 std::vector<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 // Describes a perf event for two purposes: 55 // * encoding the event in the perf_event_open syscall 56 // * echoing the counter's config in the trace packet defaults, so that the 57 // parser can tell which datastream belongs to which counter. 58 // Note: It's slightly odd to decode & pass around values we don't use outside 59 // of reencoding back into a defaults proto. One option would be to carry the 60 // Timebase proto, but this won't fit with the eventual support of multiple 61 // counters, as at the proto level it'll be a distinct message from Timebase. 62 struct PerfCounter { 63 enum class Type { kBuiltinCounter, kTracepoint, kRawEvent }; 64 65 Type type = Type::kBuiltinCounter; 66 67 // Optional config-supplied name for the counter, to identify it during 68 // trace parsing, does not affect the syscall. 69 std::string name; 70 71 // valid if kBuiltinCounter 72 protos::gen::PerfEvents::Counter counter = 73 protos::gen::PerfEvents::PerfEvents::UNKNOWN_COUNTER; 74 // valid if kTracepoint. Example: "sched:sched_switch". 75 std::string tracepoint_name; 76 // valid if kTracepoint 77 std::string tracepoint_filter; 78 79 // sycall-level description of the event (perf_event_attr): 80 uint32_t attr_type = 0; 81 uint64_t attr_config = 0; 82 uint64_t attr_config1 = 0; // optional extension 83 uint64_t attr_config2 = 0; // optional extension 84 event_typePerfCounter85 Type event_type() const { return type; } 86 87 static PerfCounter BuiltinCounter(std::string name, 88 protos::gen::PerfEvents::Counter counter, 89 uint32_t type, 90 uint64_t config); 91 92 static PerfCounter Tracepoint(std::string name, 93 std::string tracepoint_name, 94 std::string tracepoint_filter, 95 uint64_t id); 96 97 static PerfCounter RawEvent(std::string name, 98 uint32_t type, 99 uint64_t config, 100 uint64_t config1, 101 uint64_t config2); 102 }; 103 104 // Describes a single profiling configuration. Bridges the gap between the data 105 // source config proto, and the raw "perf_event_attr" structs to pass to the 106 // perf_event_open syscall. 107 class EventConfig { 108 public: 109 using tracepoint_id_fn_t = 110 std::function<uint32_t(const std::string&, const std::string&)>; 111 112 static base::Optional<EventConfig> Create( 113 const DataSourceConfig& ds_config, 114 tracepoint_id_fn_t tracepoint_id_lookup = 115 [](const std::string&, const std::string&) { return 0; }); 116 117 static base::Optional<EventConfig> Create( 118 const protos::gen::PerfEventConfig& pb_config, 119 const DataSourceConfig& raw_ds_config, 120 tracepoint_id_fn_t tracepoint_id_lookup); 121 ring_buffer_pages()122 uint32_t ring_buffer_pages() const { return ring_buffer_pages_; } read_tick_period_ms()123 uint32_t read_tick_period_ms() const { return read_tick_period_ms_; } samples_per_tick_limit()124 uint64_t samples_per_tick_limit() const { return samples_per_tick_limit_; } remote_descriptor_timeout_ms()125 uint32_t remote_descriptor_timeout_ms() const { 126 return remote_descriptor_timeout_ms_; 127 } unwind_state_clear_period_ms()128 uint32_t unwind_state_clear_period_ms() const { 129 return unwind_state_clear_period_ms_; 130 } max_enqueued_footprint_bytes()131 uint64_t max_enqueued_footprint_bytes() const { 132 return max_enqueued_footprint_bytes_; 133 } sample_callstacks()134 bool sample_callstacks() const { return sample_callstacks_; } filter()135 const TargetFilter& filter() const { return target_filter_; } kernel_frames()136 bool kernel_frames() const { return kernel_frames_; } perf_attr()137 perf_event_attr* perf_attr() const { 138 return const_cast<perf_event_attr*>(&perf_event_attr_); 139 } timebase_event()140 const PerfCounter& timebase_event() const { return timebase_event_; } target_installed_by()141 const std::vector<std::string>& target_installed_by() const { 142 return target_installed_by_; 143 } raw_ds_config()144 const DataSourceConfig& raw_ds_config() const { return raw_ds_config_; } 145 146 private: 147 EventConfig(const DataSourceConfig& raw_ds_config, 148 const perf_event_attr& pe, 149 const PerfCounter& timebase_event, 150 bool sample_callstacks, 151 TargetFilter target_filter, 152 bool kernel_frames, 153 uint32_t ring_buffer_pages, 154 uint32_t read_tick_period_ms, 155 uint64_t samples_per_tick_limit, 156 uint32_t remote_descriptor_timeout_ms, 157 uint32_t unwind_state_clear_period_ms, 158 uint64_t max_enqueued_footprint_bytes, 159 std::vector<std::string> target_installed_by); 160 161 // Parameter struct for the leader (timebase) perf_event_open syscall. 162 perf_event_attr perf_event_attr_ = {}; 163 164 // Leader event, which is already described by |perf_event_attr_|. But this 165 // additionally carries a tracepoint filter if that needs to be set via an 166 // ioctl after creating the event. 167 const PerfCounter timebase_event_; 168 169 // TODO(rsavitski): consider adding an Optional<CallstackSampling> that 170 // contains the kernel_frames_ and target_filter, once the complexity warrants 171 // it. 172 const bool sample_callstacks_; 173 174 // Parsed allow/deny-list for filtering samples. 175 const TargetFilter target_filter_; 176 177 // If true, include kernel frames in the callstacks. 178 const bool kernel_frames_; 179 180 // Size (in 4k pages) of each per-cpu ring buffer shared with the kernel. 181 // Must be a power of two. 182 const uint32_t ring_buffer_pages_; 183 184 // How often the ring buffers should be read. 185 const uint32_t read_tick_period_ms_; 186 187 // Guardrail for the amount of samples a given read attempt will extract from 188 // *each* per-cpu buffer. 189 const uint64_t samples_per_tick_limit_; 190 191 // Timeout for proc-fd lookup. 192 const uint32_t remote_descriptor_timeout_ms_; 193 194 // Optional period for clearing cached unwinder state. Skipped if zero. 195 const uint32_t unwind_state_clear_period_ms_; 196 197 const uint64_t max_enqueued_footprint_bytes_; 198 199 // Only profile target if it was installed by one of the packages given. 200 // Special values are: 201 // * "@system": installed on the system partition 202 // * "@product": installed on the product partition 203 // * "@null": sideloaded 204 const std::vector<std::string> target_installed_by_; 205 206 // The raw data source config, as a pbzero-generated C++ class. 207 const DataSourceConfig raw_ds_config_; 208 }; 209 210 } // namespace profiling 211 } // namespace perfetto 212 213 #endif // SRC_PROFILING_PERF_EVENT_CONFIG_H_ 214