1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #ifndef __PERF_PARSE_EVENTS_H |
3 | #define __PERF_PARSE_EVENTS_H |
4 | /* |
5 | * Parse symbolic events/counts passed in as options: |
6 | */ |
7 | |
8 | #include <linux/list.h> |
9 | #include <stdbool.h> |
10 | #include <linux/types.h> |
11 | #include <linux/perf_event.h> |
12 | #include <stdio.h> |
13 | #include <string.h> |
14 | |
15 | struct evsel; |
16 | struct evlist; |
17 | struct parse_events_error; |
18 | |
19 | struct option; |
20 | struct perf_pmu; |
21 | struct strbuf; |
22 | |
23 | const char *event_type(int type); |
24 | |
25 | /* Arguments encoded in opt->value. */ |
26 | struct parse_events_option_args { |
27 | struct evlist **evlistp; |
28 | const char *pmu_filter; |
29 | }; |
30 | int parse_events_option(const struct option *opt, const char *str, int unset); |
31 | int parse_events_option_new_evlist(const struct option *opt, const char *str, int unset); |
32 | __attribute__((nonnull(1, 2, 4))) |
33 | int __parse_events(struct evlist *evlist, const char *str, const char *pmu_filter, |
34 | struct parse_events_error *error, struct perf_pmu *fake_pmu, |
35 | bool warn_if_reordered); |
36 | |
37 | __attribute__((nonnull(1, 2, 3))) |
38 | static inline int parse_events(struct evlist *evlist, const char *str, |
39 | struct parse_events_error *err) |
40 | { |
41 | return __parse_events(evlist, str, /*pmu_filter=*/NULL, error: err, /*fake_pmu=*/NULL, |
42 | /*warn_if_reordered=*/warn_if_reordered: true); |
43 | } |
44 | |
45 | int parse_event(struct evlist *evlist, const char *str); |
46 | |
47 | int parse_filter(const struct option *opt, const char *str, int unset); |
48 | int exclude_perf(const struct option *opt, const char *arg, int unset); |
49 | |
50 | enum parse_events__term_val_type { |
51 | PARSE_EVENTS__TERM_TYPE_NUM, |
52 | PARSE_EVENTS__TERM_TYPE_STR, |
53 | }; |
54 | |
55 | enum parse_events__term_type { |
56 | PARSE_EVENTS__TERM_TYPE_USER, |
57 | PARSE_EVENTS__TERM_TYPE_CONFIG, |
58 | PARSE_EVENTS__TERM_TYPE_CONFIG1, |
59 | PARSE_EVENTS__TERM_TYPE_CONFIG2, |
60 | PARSE_EVENTS__TERM_TYPE_CONFIG3, |
61 | PARSE_EVENTS__TERM_TYPE_NAME, |
62 | PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD, |
63 | PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ, |
64 | PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE, |
65 | PARSE_EVENTS__TERM_TYPE_TIME, |
66 | PARSE_EVENTS__TERM_TYPE_CALLGRAPH, |
67 | PARSE_EVENTS__TERM_TYPE_STACKSIZE, |
68 | PARSE_EVENTS__TERM_TYPE_NOINHERIT, |
69 | PARSE_EVENTS__TERM_TYPE_INHERIT, |
70 | PARSE_EVENTS__TERM_TYPE_MAX_STACK, |
71 | PARSE_EVENTS__TERM_TYPE_MAX_EVENTS, |
72 | PARSE_EVENTS__TERM_TYPE_NOOVERWRITE, |
73 | PARSE_EVENTS__TERM_TYPE_OVERWRITE, |
74 | PARSE_EVENTS__TERM_TYPE_DRV_CFG, |
75 | PARSE_EVENTS__TERM_TYPE_PERCORE, |
76 | PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT, |
77 | PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE, |
78 | PARSE_EVENTS__TERM_TYPE_METRIC_ID, |
79 | PARSE_EVENTS__TERM_TYPE_RAW, |
80 | PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE, |
81 | PARSE_EVENTS__TERM_TYPE_HARDWARE, |
82 | #define __PARSE_EVENTS__TERM_TYPE_NR (PARSE_EVENTS__TERM_TYPE_HARDWARE + 1) |
83 | }; |
84 | |
85 | struct parse_events_term { |
86 | /** @list: The term list the term is a part of. */ |
87 | struct list_head list; |
88 | /** |
89 | * @config: The left-hand side of a term assignment, so the term |
90 | * "event=8" would have the config be "event" |
91 | */ |
92 | const char *config; |
93 | /** |
94 | * @val: The right-hand side of a term assignment that can either be a |
95 | * string or a number depending on type_val. |
96 | */ |
97 | union { |
98 | char *str; |
99 | u64 num; |
100 | } val; |
101 | /** @type_val: The union variable in val to be used for the term. */ |
102 | enum parse_events__term_val_type type_val; |
103 | /** |
104 | * @type_term: A predefined term type or PARSE_EVENTS__TERM_TYPE_USER |
105 | * when not inbuilt. |
106 | */ |
107 | enum parse_events__term_type type_term; |
108 | /** |
109 | * @err_term: The column index of the term from parsing, used during |
110 | * error output. |
111 | */ |
112 | int err_term; |
113 | /** |
114 | * @err_val: The column index of the val from parsing, used during error |
115 | * output. |
116 | */ |
117 | int err_val; |
118 | /** @used: Was the term used during parameterized-eval. */ |
119 | bool used; |
120 | /** |
121 | * @weak: A term from the sysfs or json encoding of an event that |
122 | * shouldn't override terms coming from the command line. |
123 | */ |
124 | bool weak; |
125 | /** |
126 | * @no_value: Is there no value. If a numeric term has no value then the |
127 | * value is assumed to be 1. An event name also has no value. |
128 | */ |
129 | bool no_value; |
130 | }; |
131 | |
132 | struct parse_events_error { |
133 | /** @list: The head of a list of errors. */ |
134 | struct list_head list; |
135 | }; |
136 | |
137 | /* A wrapper around a list of terms for the sake of better type safety. */ |
138 | struct parse_events_terms { |
139 | struct list_head terms; |
140 | }; |
141 | |
142 | struct parse_events_state { |
143 | /* The list parsed events are placed on. */ |
144 | struct list_head list; |
145 | /* The updated index used by entries as they are added. */ |
146 | int idx; |
147 | /* Error information. */ |
148 | struct parse_events_error *error; |
149 | /* Holds returned terms for term parsing. */ |
150 | struct parse_events_terms *terms; |
151 | /* Start token. */ |
152 | int stoken; |
153 | /* Special fake PMU marker for testing. */ |
154 | struct perf_pmu *fake_pmu; |
155 | /* If non-null, when wildcard matching only match the given PMU. */ |
156 | const char *pmu_filter; |
157 | /* Should PE_LEGACY_NAME tokens be generated for config terms? */ |
158 | bool match_legacy_cache_terms; |
159 | /* Were multiple PMUs scanned to find events? */ |
160 | bool wild_card_pmus; |
161 | }; |
162 | |
163 | bool parse_events__filter_pmu(const struct parse_events_state *parse_state, |
164 | const struct perf_pmu *pmu); |
165 | void parse_events__shrink_config_terms(void); |
166 | int parse_events__is_hardcoded_term(struct parse_events_term *term); |
167 | int parse_events_term__num(struct parse_events_term **term, |
168 | enum parse_events__term_type type_term, |
169 | const char *config, u64 num, |
170 | bool novalue, |
171 | void *loc_term, void *loc_val); |
172 | int parse_events_term__str(struct parse_events_term **term, |
173 | enum parse_events__term_type type_term, |
174 | char *config, char *str, |
175 | void *loc_term, void *loc_val); |
176 | int parse_events_term__term(struct parse_events_term **term, |
177 | enum parse_events__term_type term_lhs, |
178 | enum parse_events__term_type term_rhs, |
179 | void *loc_term, void *loc_val); |
180 | int parse_events_term__clone(struct parse_events_term **new, |
181 | struct parse_events_term *term); |
182 | void parse_events_term__delete(struct parse_events_term *term); |
183 | |
184 | void parse_events_terms__delete(struct parse_events_terms *terms); |
185 | void parse_events_terms__init(struct parse_events_terms *terms); |
186 | void parse_events_terms__exit(struct parse_events_terms *terms); |
187 | int parse_events_terms(struct parse_events_terms *terms, const char *str, FILE *input); |
188 | int parse_events_terms__to_strbuf(const struct parse_events_terms *terms, struct strbuf *sb); |
189 | int parse_events__modifier_event(struct list_head *list, char *str, bool add); |
190 | int parse_events__modifier_group(struct list_head *list, char *event_mod); |
191 | int parse_events_name(struct list_head *list, const char *name); |
192 | int parse_events_add_tracepoint(struct list_head *list, int *idx, |
193 | const char *sys, const char *event, |
194 | struct parse_events_error *error, |
195 | struct parse_events_terms *head_config, void *loc); |
196 | int parse_events_add_numeric(struct parse_events_state *parse_state, |
197 | struct list_head *list, |
198 | u32 type, u64 config, |
199 | struct parse_events_terms *head_config, |
200 | bool wildcard); |
201 | int parse_events_add_tool(struct parse_events_state *parse_state, |
202 | struct list_head *list, |
203 | int tool_event); |
204 | int parse_events_add_cache(struct list_head *list, int *idx, const char *name, |
205 | struct parse_events_state *parse_state, |
206 | struct parse_events_terms *head_config); |
207 | int parse_events__decode_legacy_cache(const char *name, int pmu_type, __u64 *config); |
208 | int parse_events_add_breakpoint(struct parse_events_state *parse_state, |
209 | struct list_head *list, |
210 | u64 addr, char *type, u64 len, |
211 | struct parse_events_terms *head_config); |
212 | int parse_events_add_pmu(struct parse_events_state *parse_state, |
213 | struct list_head *list, const char *name, |
214 | const struct parse_events_terms *const_parsed_terms, |
215 | bool auto_merge_stats, void *loc); |
216 | |
217 | struct evsel *parse_events__add_event(int idx, struct perf_event_attr *attr, |
218 | const char *name, const char *metric_id, |
219 | struct perf_pmu *pmu); |
220 | |
221 | int parse_events_multi_pmu_add(struct parse_events_state *parse_state, |
222 | const char *event_name, |
223 | const struct parse_events_terms *const_parsed_terms, |
224 | struct list_head **listp, void *loc); |
225 | |
226 | void parse_events__set_leader(char *name, struct list_head *list); |
227 | void parse_events_update_lists(struct list_head *list_event, |
228 | struct list_head *list_all); |
229 | void parse_events_evlist_error(struct parse_events_state *parse_state, |
230 | int idx, const char *str); |
231 | |
232 | struct event_symbol { |
233 | const char *symbol; |
234 | const char *alias; |
235 | }; |
236 | extern struct event_symbol event_symbols_hw[]; |
237 | extern struct event_symbol event_symbols_sw[]; |
238 | |
239 | char *parse_events_formats_error_string(char *additional_terms); |
240 | |
241 | void parse_events_error__init(struct parse_events_error *err); |
242 | void parse_events_error__exit(struct parse_events_error *err); |
243 | void parse_events_error__handle(struct parse_events_error *err, int idx, |
244 | char *str, char *help); |
245 | void parse_events_error__print(const struct parse_events_error *err, |
246 | const char *event); |
247 | bool parse_events_error__contains(const struct parse_events_error *err, |
248 | const char *needle); |
249 | #ifdef HAVE_LIBELF_SUPPORT |
250 | /* |
251 | * If the probe point starts with '%', |
252 | * or starts with "sdt_" and has a ':' but no '=', |
253 | * then it should be a SDT/cached probe point. |
254 | */ |
255 | static inline bool is_sdt_event(char *str) |
256 | { |
257 | return (str[0] == '%' || |
258 | (!strncmp(str, "sdt_" , 4) && |
259 | !!strchr(str, ':') && !strchr(str, '='))); |
260 | } |
261 | #else |
262 | static inline bool is_sdt_event(char *str __maybe_unused) |
263 | { |
264 | return false; |
265 | } |
266 | #endif /* HAVE_LIBELF_SUPPORT */ |
267 | |
268 | #endif /* __PERF_PARSE_EVENTS_H */ |
269 | |