.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> |
---|
3 | 4 | * |
---|
4 | 5 | * Parts came from builtin-{top,stat,record}.c, see those files for further |
---|
5 | 6 | * copyright notes. |
---|
6 | | - * |
---|
7 | | - * Released under the GPL v2. (and only v2, not any later version) |
---|
8 | 7 | */ |
---|
9 | 8 | |
---|
10 | 9 | #include <byteswap.h> |
---|
.. | .. |
---|
18 | 17 | #include <linux/perf_event.h> |
---|
19 | 18 | #include <linux/compiler.h> |
---|
20 | 19 | #include <linux/err.h> |
---|
| 20 | +#include <linux/zalloc.h> |
---|
21 | 21 | #include <sys/ioctl.h> |
---|
22 | 22 | #include <sys/resource.h> |
---|
23 | 23 | #include <sys/types.h> |
---|
24 | 24 | #include <dirent.h> |
---|
| 25 | +#include <stdlib.h> |
---|
| 26 | +#include <perf/evsel.h> |
---|
25 | 27 | #include "asm/bug.h" |
---|
26 | 28 | #include "callchain.h" |
---|
27 | 29 | #include "cgroup.h" |
---|
| 30 | +#include "counts.h" |
---|
28 | 31 | #include "event.h" |
---|
29 | 32 | #include "evsel.h" |
---|
| 33 | +#include "util/env.h" |
---|
| 34 | +#include "util/evsel_config.h" |
---|
| 35 | +#include "util/evsel_fprintf.h" |
---|
30 | 36 | #include "evlist.h" |
---|
31 | | -#include "util.h" |
---|
32 | | -#include "cpumap.h" |
---|
| 37 | +#include <perf/cpumap.h> |
---|
33 | 38 | #include "thread_map.h" |
---|
34 | 39 | #include "target.h" |
---|
35 | 40 | #include "perf_regs.h" |
---|
| 41 | +#include "record.h" |
---|
36 | 42 | #include "debug.h" |
---|
37 | 43 | #include "trace-event.h" |
---|
38 | 44 | #include "stat.h" |
---|
| 45 | +#include "string2.h" |
---|
39 | 46 | #include "memswap.h" |
---|
| 47 | +#include "util.h" |
---|
| 48 | +#include "../perf-sys.h" |
---|
40 | 49 | #include "util/parse-branch-options.h" |
---|
| 50 | +#include <internal/xyarray.h> |
---|
| 51 | +#include <internal/lib.h> |
---|
41 | 52 | |
---|
42 | | -#include "sane_ctype.h" |
---|
| 53 | +#include <linux/ctype.h> |
---|
43 | 54 | |
---|
44 | 55 | struct perf_missing_features perf_missing_features; |
---|
45 | 56 | |
---|
46 | 57 | static clockid_t clockid; |
---|
47 | 58 | |
---|
48 | | -static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused) |
---|
| 59 | +static int evsel__no_extra_init(struct evsel *evsel __maybe_unused) |
---|
49 | 60 | { |
---|
50 | 61 | return 0; |
---|
51 | 62 | } |
---|
52 | 63 | |
---|
53 | 64 | void __weak test_attr__ready(void) { } |
---|
54 | 65 | |
---|
55 | | -static void perf_evsel__no_extra_fini(struct perf_evsel *evsel __maybe_unused) |
---|
| 66 | +static void evsel__no_extra_fini(struct evsel *evsel __maybe_unused) |
---|
56 | 67 | { |
---|
57 | 68 | } |
---|
58 | 69 | |
---|
59 | 70 | static struct { |
---|
60 | 71 | size_t size; |
---|
61 | | - int (*init)(struct perf_evsel *evsel); |
---|
62 | | - void (*fini)(struct perf_evsel *evsel); |
---|
| 72 | + int (*init)(struct evsel *evsel); |
---|
| 73 | + void (*fini)(struct evsel *evsel); |
---|
63 | 74 | } perf_evsel__object = { |
---|
64 | | - .size = sizeof(struct perf_evsel), |
---|
65 | | - .init = perf_evsel__no_extra_init, |
---|
66 | | - .fini = perf_evsel__no_extra_fini, |
---|
| 75 | + .size = sizeof(struct evsel), |
---|
| 76 | + .init = evsel__no_extra_init, |
---|
| 77 | + .fini = evsel__no_extra_fini, |
---|
67 | 78 | }; |
---|
68 | 79 | |
---|
69 | | -int perf_evsel__object_config(size_t object_size, |
---|
70 | | - int (*init)(struct perf_evsel *evsel), |
---|
71 | | - void (*fini)(struct perf_evsel *evsel)) |
---|
| 80 | +int evsel__object_config(size_t object_size, int (*init)(struct evsel *evsel), |
---|
| 81 | + void (*fini)(struct evsel *evsel)) |
---|
72 | 82 | { |
---|
73 | 83 | |
---|
74 | 84 | if (object_size == 0) |
---|
.. | .. |
---|
89 | 99 | return 0; |
---|
90 | 100 | } |
---|
91 | 101 | |
---|
92 | | -#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) |
---|
| 102 | +#define FD(e, x, y) (*(int *)xyarray__entry(e->core.fd, x, y)) |
---|
93 | 103 | |
---|
94 | | -int __perf_evsel__sample_size(u64 sample_type) |
---|
| 104 | +int __evsel__sample_size(u64 sample_type) |
---|
95 | 105 | { |
---|
96 | 106 | u64 mask = sample_type & PERF_SAMPLE_MASK; |
---|
97 | 107 | int size = 0; |
---|
.. | .. |
---|
113 | 123 | * |
---|
114 | 124 | * This function returns the position of the event id (PERF_SAMPLE_ID or |
---|
115 | 125 | * PERF_SAMPLE_IDENTIFIER) in a sample event i.e. in the array of struct |
---|
116 | | - * sample_event. |
---|
| 126 | + * perf_record_sample. |
---|
117 | 127 | */ |
---|
118 | 128 | static int __perf_evsel__calc_id_pos(u64 sample_type) |
---|
119 | 129 | { |
---|
.. | .. |
---|
167 | 177 | return idx; |
---|
168 | 178 | } |
---|
169 | 179 | |
---|
170 | | -void perf_evsel__calc_id_pos(struct perf_evsel *evsel) |
---|
| 180 | +void evsel__calc_id_pos(struct evsel *evsel) |
---|
171 | 181 | { |
---|
172 | | - evsel->id_pos = __perf_evsel__calc_id_pos(evsel->attr.sample_type); |
---|
173 | | - evsel->is_pos = __perf_evsel__calc_is_pos(evsel->attr.sample_type); |
---|
| 182 | + evsel->id_pos = __perf_evsel__calc_id_pos(evsel->core.attr.sample_type); |
---|
| 183 | + evsel->is_pos = __perf_evsel__calc_is_pos(evsel->core.attr.sample_type); |
---|
174 | 184 | } |
---|
175 | 185 | |
---|
176 | | -void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, |
---|
| 186 | +void __evsel__set_sample_bit(struct evsel *evsel, |
---|
177 | 187 | enum perf_event_sample_format bit) |
---|
178 | 188 | { |
---|
179 | | - if (!(evsel->attr.sample_type & bit)) { |
---|
180 | | - evsel->attr.sample_type |= bit; |
---|
| 189 | + if (!(evsel->core.attr.sample_type & bit)) { |
---|
| 190 | + evsel->core.attr.sample_type |= bit; |
---|
181 | 191 | evsel->sample_size += sizeof(u64); |
---|
182 | | - perf_evsel__calc_id_pos(evsel); |
---|
| 192 | + evsel__calc_id_pos(evsel); |
---|
183 | 193 | } |
---|
184 | 194 | } |
---|
185 | 195 | |
---|
186 | | -void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel, |
---|
| 196 | +void __evsel__reset_sample_bit(struct evsel *evsel, |
---|
187 | 197 | enum perf_event_sample_format bit) |
---|
188 | 198 | { |
---|
189 | | - if (evsel->attr.sample_type & bit) { |
---|
190 | | - evsel->attr.sample_type &= ~bit; |
---|
| 199 | + if (evsel->core.attr.sample_type & bit) { |
---|
| 200 | + evsel->core.attr.sample_type &= ~bit; |
---|
191 | 201 | evsel->sample_size -= sizeof(u64); |
---|
192 | | - perf_evsel__calc_id_pos(evsel); |
---|
| 202 | + evsel__calc_id_pos(evsel); |
---|
193 | 203 | } |
---|
194 | 204 | } |
---|
195 | 205 | |
---|
196 | | -void perf_evsel__set_sample_id(struct perf_evsel *evsel, |
---|
| 206 | +void evsel__set_sample_id(struct evsel *evsel, |
---|
197 | 207 | bool can_sample_identifier) |
---|
198 | 208 | { |
---|
199 | 209 | if (can_sample_identifier) { |
---|
200 | | - perf_evsel__reset_sample_bit(evsel, ID); |
---|
201 | | - perf_evsel__set_sample_bit(evsel, IDENTIFIER); |
---|
| 210 | + evsel__reset_sample_bit(evsel, ID); |
---|
| 211 | + evsel__set_sample_bit(evsel, IDENTIFIER); |
---|
202 | 212 | } else { |
---|
203 | | - perf_evsel__set_sample_bit(evsel, ID); |
---|
| 213 | + evsel__set_sample_bit(evsel, ID); |
---|
204 | 214 | } |
---|
205 | | - evsel->attr.read_format |= PERF_FORMAT_ID; |
---|
| 215 | + evsel->core.attr.read_format |= PERF_FORMAT_ID; |
---|
206 | 216 | } |
---|
207 | 217 | |
---|
208 | 218 | /** |
---|
209 | | - * perf_evsel__is_function_event - Return whether given evsel is a function |
---|
| 219 | + * evsel__is_function_event - Return whether given evsel is a function |
---|
210 | 220 | * trace event |
---|
211 | 221 | * |
---|
212 | 222 | * @evsel - evsel selector to be tested |
---|
213 | 223 | * |
---|
214 | 224 | * Return %true if event is function trace event |
---|
215 | 225 | */ |
---|
216 | | -bool perf_evsel__is_function_event(struct perf_evsel *evsel) |
---|
| 226 | +bool evsel__is_function_event(struct evsel *evsel) |
---|
217 | 227 | { |
---|
218 | 228 | #define FUNCTION_EVENT "ftrace:function" |
---|
219 | 229 | |
---|
.. | .. |
---|
223 | 233 | #undef FUNCTION_EVENT |
---|
224 | 234 | } |
---|
225 | 235 | |
---|
226 | | -void perf_evsel__init(struct perf_evsel *evsel, |
---|
227 | | - struct perf_event_attr *attr, int idx) |
---|
| 236 | +void evsel__init(struct evsel *evsel, |
---|
| 237 | + struct perf_event_attr *attr, int idx) |
---|
228 | 238 | { |
---|
| 239 | + perf_evsel__init(&evsel->core, attr); |
---|
229 | 240 | evsel->idx = idx; |
---|
230 | 241 | evsel->tracking = !idx; |
---|
231 | | - evsel->attr = *attr; |
---|
232 | 242 | evsel->leader = evsel; |
---|
233 | 243 | evsel->unit = ""; |
---|
234 | 244 | evsel->scale = 1.0; |
---|
| 245 | + evsel->max_events = ULONG_MAX; |
---|
235 | 246 | evsel->evlist = NULL; |
---|
| 247 | + evsel->bpf_obj = NULL; |
---|
236 | 248 | evsel->bpf_fd = -1; |
---|
237 | | - INIT_LIST_HEAD(&evsel->node); |
---|
238 | 249 | INIT_LIST_HEAD(&evsel->config_terms); |
---|
239 | 250 | perf_evsel__object.init(evsel); |
---|
240 | | - evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); |
---|
241 | | - perf_evsel__calc_id_pos(evsel); |
---|
| 251 | + evsel->sample_size = __evsel__sample_size(attr->sample_type); |
---|
| 252 | + evsel__calc_id_pos(evsel); |
---|
242 | 253 | evsel->cmdline_group_boundary = false; |
---|
243 | 254 | evsel->metric_expr = NULL; |
---|
244 | 255 | evsel->metric_name = NULL; |
---|
245 | 256 | evsel->metric_events = NULL; |
---|
| 257 | + evsel->per_pkg_mask = NULL; |
---|
246 | 258 | evsel->collect_stat = false; |
---|
247 | 259 | evsel->pmu_name = NULL; |
---|
248 | 260 | } |
---|
249 | 261 | |
---|
250 | | -struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) |
---|
| 262 | +struct evsel *evsel__new_idx(struct perf_event_attr *attr, int idx) |
---|
251 | 263 | { |
---|
252 | | - struct perf_evsel *evsel = zalloc(perf_evsel__object.size); |
---|
| 264 | + struct evsel *evsel = zalloc(perf_evsel__object.size); |
---|
253 | 265 | |
---|
254 | 266 | if (!evsel) |
---|
255 | 267 | return NULL; |
---|
256 | | - perf_evsel__init(evsel, attr, idx); |
---|
| 268 | + evsel__init(evsel, attr, idx); |
---|
257 | 269 | |
---|
258 | | - if (perf_evsel__is_bpf_output(evsel)) { |
---|
259 | | - evsel->attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | |
---|
| 270 | + if (evsel__is_bpf_output(evsel)) { |
---|
| 271 | + evsel->core.attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | |
---|
260 | 272 | PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD), |
---|
261 | | - evsel->attr.sample_period = 1; |
---|
| 273 | + evsel->core.attr.sample_period = 1; |
---|
262 | 274 | } |
---|
263 | 275 | |
---|
264 | | - if (perf_evsel__is_clock(evsel)) { |
---|
| 276 | + if (evsel__is_clock(evsel)) { |
---|
265 | 277 | /* |
---|
266 | 278 | * The evsel->unit points to static alias->unit |
---|
267 | 279 | * so it's ok to use static string in here. |
---|
.. | .. |
---|
277 | 289 | |
---|
278 | 290 | static bool perf_event_can_profile_kernel(void) |
---|
279 | 291 | { |
---|
280 | | - return geteuid() == 0 || perf_event_paranoid() == -1; |
---|
| 292 | + return perf_event_paranoid_check(1); |
---|
281 | 293 | } |
---|
282 | 294 | |
---|
283 | | -struct perf_evsel *perf_evsel__new_cycles(bool precise) |
---|
| 295 | +struct evsel *evsel__new_cycles(bool precise) |
---|
284 | 296 | { |
---|
285 | 297 | struct perf_event_attr attr = { |
---|
286 | 298 | .type = PERF_TYPE_HARDWARE, |
---|
287 | 299 | .config = PERF_COUNT_HW_CPU_CYCLES, |
---|
288 | 300 | .exclude_kernel = !perf_event_can_profile_kernel(), |
---|
289 | 301 | }; |
---|
290 | | - struct perf_evsel *evsel; |
---|
| 302 | + struct evsel *evsel; |
---|
291 | 303 | |
---|
292 | 304 | event_attr_init(&attr); |
---|
293 | 305 | |
---|
294 | 306 | if (!precise) |
---|
295 | 307 | goto new_event; |
---|
296 | | - /* |
---|
297 | | - * Unnamed union member, not supported as struct member named |
---|
298 | | - * initializer in older compilers such as gcc 4.4.7 |
---|
299 | | - * |
---|
300 | | - * Just for probing the precise_ip: |
---|
301 | | - */ |
---|
302 | | - attr.sample_period = 1; |
---|
303 | 308 | |
---|
304 | | - perf_event_attr__set_max_precise_ip(&attr); |
---|
305 | 309 | /* |
---|
306 | 310 | * Now let the usual logic to set up the perf_event_attr defaults |
---|
307 | 311 | * to kick in when we return and before perf_evsel__open() is called. |
---|
308 | 312 | */ |
---|
309 | | - attr.sample_period = 0; |
---|
310 | 313 | new_event: |
---|
311 | | - evsel = perf_evsel__new(&attr); |
---|
| 314 | + evsel = evsel__new(&attr); |
---|
312 | 315 | if (evsel == NULL) |
---|
313 | 316 | goto out; |
---|
| 317 | + |
---|
| 318 | + evsel->precise_max = true; |
---|
314 | 319 | |
---|
315 | 320 | /* use asprintf() because free(evsel) assumes name is allocated */ |
---|
316 | 321 | if (asprintf(&evsel->name, "cycles%s%s%.*s", |
---|
.. | .. |
---|
321 | 326 | out: |
---|
322 | 327 | return evsel; |
---|
323 | 328 | error_free: |
---|
324 | | - perf_evsel__delete(evsel); |
---|
| 329 | + evsel__delete(evsel); |
---|
325 | 330 | evsel = NULL; |
---|
326 | 331 | goto out; |
---|
| 332 | +} |
---|
| 333 | + |
---|
| 334 | +static int evsel__copy_config_terms(struct evsel *dst, struct evsel *src) |
---|
| 335 | +{ |
---|
| 336 | + struct evsel_config_term *pos, *tmp; |
---|
| 337 | + |
---|
| 338 | + list_for_each_entry(pos, &src->config_terms, list) { |
---|
| 339 | + tmp = malloc(sizeof(*tmp)); |
---|
| 340 | + if (tmp == NULL) |
---|
| 341 | + return -ENOMEM; |
---|
| 342 | + |
---|
| 343 | + *tmp = *pos; |
---|
| 344 | + if (tmp->free_str) { |
---|
| 345 | + tmp->val.str = strdup(pos->val.str); |
---|
| 346 | + if (tmp->val.str == NULL) { |
---|
| 347 | + free(tmp); |
---|
| 348 | + return -ENOMEM; |
---|
| 349 | + } |
---|
| 350 | + } |
---|
| 351 | + list_add_tail(&tmp->list, &dst->config_terms); |
---|
| 352 | + } |
---|
| 353 | + return 0; |
---|
| 354 | +} |
---|
| 355 | + |
---|
| 356 | +/** |
---|
| 357 | + * evsel__clone - create a new evsel copied from @orig |
---|
| 358 | + * @orig: original evsel |
---|
| 359 | + * |
---|
| 360 | + * The assumption is that @orig is not configured nor opened yet. |
---|
| 361 | + * So we only care about the attributes that can be set while it's parsed. |
---|
| 362 | + */ |
---|
| 363 | +struct evsel *evsel__clone(struct evsel *orig) |
---|
| 364 | +{ |
---|
| 365 | + struct evsel *evsel; |
---|
| 366 | + |
---|
| 367 | + BUG_ON(orig->core.fd); |
---|
| 368 | + BUG_ON(orig->counts); |
---|
| 369 | + BUG_ON(orig->priv); |
---|
| 370 | + BUG_ON(orig->per_pkg_mask); |
---|
| 371 | + |
---|
| 372 | + /* cannot handle BPF objects for now */ |
---|
| 373 | + if (orig->bpf_obj) |
---|
| 374 | + return NULL; |
---|
| 375 | + |
---|
| 376 | + evsel = evsel__new(&orig->core.attr); |
---|
| 377 | + if (evsel == NULL) |
---|
| 378 | + return NULL; |
---|
| 379 | + |
---|
| 380 | + evsel->core.cpus = perf_cpu_map__get(orig->core.cpus); |
---|
| 381 | + evsel->core.own_cpus = perf_cpu_map__get(orig->core.own_cpus); |
---|
| 382 | + evsel->core.threads = perf_thread_map__get(orig->core.threads); |
---|
| 383 | + evsel->core.nr_members = orig->core.nr_members; |
---|
| 384 | + evsel->core.system_wide = orig->core.system_wide; |
---|
| 385 | + |
---|
| 386 | + if (orig->name) { |
---|
| 387 | + evsel->name = strdup(orig->name); |
---|
| 388 | + if (evsel->name == NULL) |
---|
| 389 | + goto out_err; |
---|
| 390 | + } |
---|
| 391 | + if (orig->group_name) { |
---|
| 392 | + evsel->group_name = strdup(orig->group_name); |
---|
| 393 | + if (evsel->group_name == NULL) |
---|
| 394 | + goto out_err; |
---|
| 395 | + } |
---|
| 396 | + if (orig->pmu_name) { |
---|
| 397 | + evsel->pmu_name = strdup(orig->pmu_name); |
---|
| 398 | + if (evsel->pmu_name == NULL) |
---|
| 399 | + goto out_err; |
---|
| 400 | + } |
---|
| 401 | + if (orig->filter) { |
---|
| 402 | + evsel->filter = strdup(orig->filter); |
---|
| 403 | + if (evsel->filter == NULL) |
---|
| 404 | + goto out_err; |
---|
| 405 | + } |
---|
| 406 | + evsel->cgrp = cgroup__get(orig->cgrp); |
---|
| 407 | + evsel->tp_format = orig->tp_format; |
---|
| 408 | + evsel->handler = orig->handler; |
---|
| 409 | + evsel->leader = orig->leader; |
---|
| 410 | + |
---|
| 411 | + evsel->max_events = orig->max_events; |
---|
| 412 | + evsel->tool_event = orig->tool_event; |
---|
| 413 | + evsel->unit = orig->unit; |
---|
| 414 | + evsel->scale = orig->scale; |
---|
| 415 | + evsel->snapshot = orig->snapshot; |
---|
| 416 | + evsel->per_pkg = orig->per_pkg; |
---|
| 417 | + evsel->percore = orig->percore; |
---|
| 418 | + evsel->precise_max = orig->precise_max; |
---|
| 419 | + evsel->use_uncore_alias = orig->use_uncore_alias; |
---|
| 420 | + evsel->is_libpfm_event = orig->is_libpfm_event; |
---|
| 421 | + |
---|
| 422 | + evsel->exclude_GH = orig->exclude_GH; |
---|
| 423 | + evsel->sample_read = orig->sample_read; |
---|
| 424 | + evsel->auto_merge_stats = orig->auto_merge_stats; |
---|
| 425 | + evsel->collect_stat = orig->collect_stat; |
---|
| 426 | + evsel->weak_group = orig->weak_group; |
---|
| 427 | + |
---|
| 428 | + if (evsel__copy_config_terms(evsel, orig) < 0) |
---|
| 429 | + goto out_err; |
---|
| 430 | + |
---|
| 431 | + return evsel; |
---|
| 432 | + |
---|
| 433 | +out_err: |
---|
| 434 | + evsel__delete(evsel); |
---|
| 435 | + return NULL; |
---|
327 | 436 | } |
---|
328 | 437 | |
---|
329 | 438 | /* |
---|
330 | 439 | * Returns pointer with encoded error via <linux/err.h> interface. |
---|
331 | 440 | */ |
---|
332 | | -struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) |
---|
| 441 | +struct evsel *evsel__newtp_idx(const char *sys, const char *name, int idx) |
---|
333 | 442 | { |
---|
334 | | - struct perf_evsel *evsel = zalloc(perf_evsel__object.size); |
---|
| 443 | + struct evsel *evsel = zalloc(perf_evsel__object.size); |
---|
335 | 444 | int err = -ENOMEM; |
---|
336 | 445 | |
---|
337 | 446 | if (evsel == NULL) { |
---|
.. | .. |
---|
355 | 464 | event_attr_init(&attr); |
---|
356 | 465 | attr.config = evsel->tp_format->id; |
---|
357 | 466 | attr.sample_period = 1; |
---|
358 | | - perf_evsel__init(evsel, &attr, idx); |
---|
| 467 | + evsel__init(evsel, &attr, idx); |
---|
359 | 468 | } |
---|
360 | 469 | |
---|
361 | 470 | return evsel; |
---|
.. | .. |
---|
367 | 476 | return ERR_PTR(err); |
---|
368 | 477 | } |
---|
369 | 478 | |
---|
370 | | -const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { |
---|
| 479 | +const char *evsel__hw_names[PERF_COUNT_HW_MAX] = { |
---|
371 | 480 | "cycles", |
---|
372 | 481 | "instructions", |
---|
373 | 482 | "cache-references", |
---|
.. | .. |
---|
380 | 489 | "ref-cycles", |
---|
381 | 490 | }; |
---|
382 | 491 | |
---|
383 | | -static const char *__perf_evsel__hw_name(u64 config) |
---|
| 492 | +static const char *__evsel__hw_name(u64 config) |
---|
384 | 493 | { |
---|
385 | | - if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config]) |
---|
386 | | - return perf_evsel__hw_names[config]; |
---|
| 494 | + if (config < PERF_COUNT_HW_MAX && evsel__hw_names[config]) |
---|
| 495 | + return evsel__hw_names[config]; |
---|
387 | 496 | |
---|
388 | 497 | return "unknown-hardware"; |
---|
389 | 498 | } |
---|
390 | 499 | |
---|
391 | | -static int perf_evsel__add_modifiers(struct perf_evsel *evsel, char *bf, size_t size) |
---|
| 500 | +static int perf_evsel__add_modifiers(struct evsel *evsel, char *bf, size_t size) |
---|
392 | 501 | { |
---|
393 | 502 | int colon = 0, r = 0; |
---|
394 | | - struct perf_event_attr *attr = &evsel->attr; |
---|
| 503 | + struct perf_event_attr *attr = &evsel->core.attr; |
---|
395 | 504 | bool exclude_guest_default = false; |
---|
396 | 505 | |
---|
397 | 506 | #define MOD_PRINT(context, mod) do { \ |
---|
.. | .. |
---|
424 | 533 | return r; |
---|
425 | 534 | } |
---|
426 | 535 | |
---|
427 | | -static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size) |
---|
| 536 | +static int evsel__hw_name(struct evsel *evsel, char *bf, size_t size) |
---|
428 | 537 | { |
---|
429 | | - int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->attr.config)); |
---|
| 538 | + int r = scnprintf(bf, size, "%s", __evsel__hw_name(evsel->core.attr.config)); |
---|
430 | 539 | return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); |
---|
431 | 540 | } |
---|
432 | 541 | |
---|
433 | | -const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = { |
---|
| 542 | +const char *evsel__sw_names[PERF_COUNT_SW_MAX] = { |
---|
434 | 543 | "cpu-clock", |
---|
435 | 544 | "task-clock", |
---|
436 | 545 | "page-faults", |
---|
.. | .. |
---|
443 | 552 | "dummy", |
---|
444 | 553 | }; |
---|
445 | 554 | |
---|
446 | | -static const char *__perf_evsel__sw_name(u64 config) |
---|
| 555 | +static const char *__evsel__sw_name(u64 config) |
---|
447 | 556 | { |
---|
448 | | - if (config < PERF_COUNT_SW_MAX && perf_evsel__sw_names[config]) |
---|
449 | | - return perf_evsel__sw_names[config]; |
---|
| 557 | + if (config < PERF_COUNT_SW_MAX && evsel__sw_names[config]) |
---|
| 558 | + return evsel__sw_names[config]; |
---|
450 | 559 | return "unknown-software"; |
---|
451 | 560 | } |
---|
452 | 561 | |
---|
453 | | -static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size) |
---|
| 562 | +static int evsel__sw_name(struct evsel *evsel, char *bf, size_t size) |
---|
454 | 563 | { |
---|
455 | | - int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->attr.config)); |
---|
| 564 | + int r = scnprintf(bf, size, "%s", __evsel__sw_name(evsel->core.attr.config)); |
---|
456 | 565 | return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); |
---|
457 | 566 | } |
---|
458 | 567 | |
---|
459 | | -static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type) |
---|
| 568 | +static int __evsel__bp_name(char *bf, size_t size, u64 addr, u64 type) |
---|
460 | 569 | { |
---|
461 | 570 | int r; |
---|
462 | 571 | |
---|
.. | .. |
---|
474 | 583 | return r; |
---|
475 | 584 | } |
---|
476 | 585 | |
---|
477 | | -static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size) |
---|
| 586 | +static int evsel__bp_name(struct evsel *evsel, char *bf, size_t size) |
---|
478 | 587 | { |
---|
479 | | - struct perf_event_attr *attr = &evsel->attr; |
---|
480 | | - int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type); |
---|
| 588 | + struct perf_event_attr *attr = &evsel->core.attr; |
---|
| 589 | + int r = __evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type); |
---|
481 | 590 | return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); |
---|
482 | 591 | } |
---|
483 | 592 | |
---|
484 | | -const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX] |
---|
485 | | - [PERF_EVSEL__MAX_ALIASES] = { |
---|
| 593 | +const char *evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX][EVSEL__MAX_ALIASES] = { |
---|
486 | 594 | { "L1-dcache", "l1-d", "l1d", "L1-data", }, |
---|
487 | 595 | { "L1-icache", "l1-i", "l1i", "L1-instruction", }, |
---|
488 | 596 | { "LLC", "L2", }, |
---|
.. | .. |
---|
492 | 600 | { "node", }, |
---|
493 | 601 | }; |
---|
494 | 602 | |
---|
495 | | -const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX] |
---|
496 | | - [PERF_EVSEL__MAX_ALIASES] = { |
---|
| 603 | +const char *evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX][EVSEL__MAX_ALIASES] = { |
---|
497 | 604 | { "load", "loads", "read", }, |
---|
498 | 605 | { "store", "stores", "write", }, |
---|
499 | 606 | { "prefetch", "prefetches", "speculative-read", "speculative-load", }, |
---|
500 | 607 | }; |
---|
501 | 608 | |
---|
502 | | -const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX] |
---|
503 | | - [PERF_EVSEL__MAX_ALIASES] = { |
---|
| 609 | +const char *evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX][EVSEL__MAX_ALIASES] = { |
---|
504 | 610 | { "refs", "Reference", "ops", "access", }, |
---|
505 | 611 | { "misses", "miss", }, |
---|
506 | 612 | }; |
---|
.. | .. |
---|
516 | 622 | * L1I : Read and prefetch only |
---|
517 | 623 | * ITLB and BPU : Read-only |
---|
518 | 624 | */ |
---|
519 | | -static unsigned long perf_evsel__hw_cache_stat[C(MAX)] = { |
---|
| 625 | +static unsigned long evsel__hw_cache_stat[C(MAX)] = { |
---|
520 | 626 | [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), |
---|
521 | 627 | [C(L1I)] = (CACHE_READ | CACHE_PREFETCH), |
---|
522 | 628 | [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), |
---|
.. | .. |
---|
526 | 632 | [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), |
---|
527 | 633 | }; |
---|
528 | 634 | |
---|
529 | | -bool perf_evsel__is_cache_op_valid(u8 type, u8 op) |
---|
| 635 | +bool evsel__is_cache_op_valid(u8 type, u8 op) |
---|
530 | 636 | { |
---|
531 | | - if (perf_evsel__hw_cache_stat[type] & COP(op)) |
---|
| 637 | + if (evsel__hw_cache_stat[type] & COP(op)) |
---|
532 | 638 | return true; /* valid */ |
---|
533 | 639 | else |
---|
534 | 640 | return false; /* invalid */ |
---|
535 | 641 | } |
---|
536 | 642 | |
---|
537 | | -int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, |
---|
538 | | - char *bf, size_t size) |
---|
| 643 | +int __evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, char *bf, size_t size) |
---|
539 | 644 | { |
---|
540 | 645 | if (result) { |
---|
541 | | - return scnprintf(bf, size, "%s-%s-%s", perf_evsel__hw_cache[type][0], |
---|
542 | | - perf_evsel__hw_cache_op[op][0], |
---|
543 | | - perf_evsel__hw_cache_result[result][0]); |
---|
| 646 | + return scnprintf(bf, size, "%s-%s-%s", evsel__hw_cache[type][0], |
---|
| 647 | + evsel__hw_cache_op[op][0], |
---|
| 648 | + evsel__hw_cache_result[result][0]); |
---|
544 | 649 | } |
---|
545 | 650 | |
---|
546 | | - return scnprintf(bf, size, "%s-%s", perf_evsel__hw_cache[type][0], |
---|
547 | | - perf_evsel__hw_cache_op[op][1]); |
---|
| 651 | + return scnprintf(bf, size, "%s-%s", evsel__hw_cache[type][0], |
---|
| 652 | + evsel__hw_cache_op[op][1]); |
---|
548 | 653 | } |
---|
549 | 654 | |
---|
550 | | -static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size) |
---|
| 655 | +static int __evsel__hw_cache_name(u64 config, char *bf, size_t size) |
---|
551 | 656 | { |
---|
552 | 657 | u8 op, result, type = (config >> 0) & 0xff; |
---|
553 | 658 | const char *err = "unknown-ext-hardware-cache-type"; |
---|
.. | .. |
---|
566 | 671 | goto out_err; |
---|
567 | 672 | |
---|
568 | 673 | err = "invalid-cache"; |
---|
569 | | - if (!perf_evsel__is_cache_op_valid(type, op)) |
---|
| 674 | + if (!evsel__is_cache_op_valid(type, op)) |
---|
570 | 675 | goto out_err; |
---|
571 | 676 | |
---|
572 | | - return __perf_evsel__hw_cache_type_op_res_name(type, op, result, bf, size); |
---|
| 677 | + return __evsel__hw_cache_type_op_res_name(type, op, result, bf, size); |
---|
573 | 678 | out_err: |
---|
574 | 679 | return scnprintf(bf, size, "%s", err); |
---|
575 | 680 | } |
---|
576 | 681 | |
---|
577 | | -static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t size) |
---|
| 682 | +static int evsel__hw_cache_name(struct evsel *evsel, char *bf, size_t size) |
---|
578 | 683 | { |
---|
579 | | - int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size); |
---|
| 684 | + int ret = __evsel__hw_cache_name(evsel->core.attr.config, bf, size); |
---|
580 | 685 | return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret); |
---|
581 | 686 | } |
---|
582 | 687 | |
---|
583 | | -static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size) |
---|
| 688 | +static int evsel__raw_name(struct evsel *evsel, char *bf, size_t size) |
---|
584 | 689 | { |
---|
585 | | - int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config); |
---|
| 690 | + int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->core.attr.config); |
---|
586 | 691 | return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret); |
---|
587 | 692 | } |
---|
588 | 693 | |
---|
589 | | -const char *perf_evsel__name(struct perf_evsel *evsel) |
---|
| 694 | +static int evsel__tool_name(char *bf, size_t size) |
---|
| 695 | +{ |
---|
| 696 | + int ret = scnprintf(bf, size, "duration_time"); |
---|
| 697 | + return ret; |
---|
| 698 | +} |
---|
| 699 | + |
---|
| 700 | +const char *evsel__name(struct evsel *evsel) |
---|
590 | 701 | { |
---|
591 | 702 | char bf[128]; |
---|
592 | 703 | |
---|
.. | .. |
---|
596 | 707 | if (evsel->name) |
---|
597 | 708 | return evsel->name; |
---|
598 | 709 | |
---|
599 | | - switch (evsel->attr.type) { |
---|
| 710 | + switch (evsel->core.attr.type) { |
---|
600 | 711 | case PERF_TYPE_RAW: |
---|
601 | | - perf_evsel__raw_name(evsel, bf, sizeof(bf)); |
---|
| 712 | + evsel__raw_name(evsel, bf, sizeof(bf)); |
---|
602 | 713 | break; |
---|
603 | 714 | |
---|
604 | 715 | case PERF_TYPE_HARDWARE: |
---|
605 | | - perf_evsel__hw_name(evsel, bf, sizeof(bf)); |
---|
| 716 | + evsel__hw_name(evsel, bf, sizeof(bf)); |
---|
606 | 717 | break; |
---|
607 | 718 | |
---|
608 | 719 | case PERF_TYPE_HW_CACHE: |
---|
609 | | - perf_evsel__hw_cache_name(evsel, bf, sizeof(bf)); |
---|
| 720 | + evsel__hw_cache_name(evsel, bf, sizeof(bf)); |
---|
610 | 721 | break; |
---|
611 | 722 | |
---|
612 | 723 | case PERF_TYPE_SOFTWARE: |
---|
613 | | - perf_evsel__sw_name(evsel, bf, sizeof(bf)); |
---|
| 724 | + if (evsel->tool_event) |
---|
| 725 | + evsel__tool_name(bf, sizeof(bf)); |
---|
| 726 | + else |
---|
| 727 | + evsel__sw_name(evsel, bf, sizeof(bf)); |
---|
614 | 728 | break; |
---|
615 | 729 | |
---|
616 | 730 | case PERF_TYPE_TRACEPOINT: |
---|
.. | .. |
---|
618 | 732 | break; |
---|
619 | 733 | |
---|
620 | 734 | case PERF_TYPE_BREAKPOINT: |
---|
621 | | - perf_evsel__bp_name(evsel, bf, sizeof(bf)); |
---|
| 735 | + evsel__bp_name(evsel, bf, sizeof(bf)); |
---|
622 | 736 | break; |
---|
623 | 737 | |
---|
624 | 738 | default: |
---|
625 | 739 | scnprintf(bf, sizeof(bf), "unknown attr type: %d", |
---|
626 | | - evsel->attr.type); |
---|
| 740 | + evsel->core.attr.type); |
---|
627 | 741 | break; |
---|
628 | 742 | } |
---|
629 | 743 | |
---|
.. | .. |
---|
635 | 749 | return "unknown"; |
---|
636 | 750 | } |
---|
637 | 751 | |
---|
638 | | -const char *perf_evsel__group_name(struct perf_evsel *evsel) |
---|
| 752 | +const char *evsel__group_name(struct evsel *evsel) |
---|
639 | 753 | { |
---|
640 | 754 | return evsel->group_name ?: "anon group"; |
---|
641 | 755 | } |
---|
.. | .. |
---|
650 | 764 | * For record -e 'cycles,instructions' and report --group |
---|
651 | 765 | * 'cycles:u, instructions:u' |
---|
652 | 766 | */ |
---|
653 | | -int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size) |
---|
| 767 | +int evsel__group_desc(struct evsel *evsel, char *buf, size_t size) |
---|
654 | 768 | { |
---|
655 | 769 | int ret = 0; |
---|
656 | | - struct perf_evsel *pos; |
---|
657 | | - const char *group_name = perf_evsel__group_name(evsel); |
---|
| 770 | + struct evsel *pos; |
---|
| 771 | + const char *group_name = evsel__group_name(evsel); |
---|
658 | 772 | |
---|
659 | 773 | if (!evsel->forced_leader) |
---|
660 | 774 | ret = scnprintf(buf, size, "%s { ", group_name); |
---|
661 | 775 | |
---|
662 | | - ret += scnprintf(buf + ret, size - ret, "%s", |
---|
663 | | - perf_evsel__name(evsel)); |
---|
| 776 | + ret += scnprintf(buf + ret, size - ret, "%s", evsel__name(evsel)); |
---|
664 | 777 | |
---|
665 | 778 | for_each_group_member(pos, evsel) |
---|
666 | | - ret += scnprintf(buf + ret, size - ret, ", %s", |
---|
667 | | - perf_evsel__name(pos)); |
---|
| 779 | + ret += scnprintf(buf + ret, size - ret, ", %s", evsel__name(pos)); |
---|
668 | 780 | |
---|
669 | 781 | if (!evsel->forced_leader) |
---|
670 | 782 | ret += scnprintf(buf + ret, size - ret, " }"); |
---|
.. | .. |
---|
672 | 784 | return ret; |
---|
673 | 785 | } |
---|
674 | 786 | |
---|
675 | | -static void __perf_evsel__config_callchain(struct perf_evsel *evsel, |
---|
676 | | - struct record_opts *opts, |
---|
677 | | - struct callchain_param *param) |
---|
| 787 | +static void __evsel__config_callchain(struct evsel *evsel, struct record_opts *opts, |
---|
| 788 | + struct callchain_param *param) |
---|
678 | 789 | { |
---|
679 | | - bool function = perf_evsel__is_function_event(evsel); |
---|
680 | | - struct perf_event_attr *attr = &evsel->attr; |
---|
| 790 | + bool function = evsel__is_function_event(evsel); |
---|
| 791 | + struct perf_event_attr *attr = &evsel->core.attr; |
---|
681 | 792 | |
---|
682 | | - perf_evsel__set_sample_bit(evsel, CALLCHAIN); |
---|
| 793 | + evsel__set_sample_bit(evsel, CALLCHAIN); |
---|
683 | 794 | |
---|
684 | 795 | attr->sample_max_stack = param->max_stack; |
---|
685 | 796 | |
---|
| 797 | + if (opts->kernel_callchains) |
---|
| 798 | + attr->exclude_callchain_user = 1; |
---|
| 799 | + if (opts->user_callchains) |
---|
| 800 | + attr->exclude_callchain_kernel = 1; |
---|
686 | 801 | if (param->record_mode == CALLCHAIN_LBR) { |
---|
687 | 802 | if (!opts->branch_stack) { |
---|
688 | 803 | if (attr->exclude_user) { |
---|
.. | .. |
---|
690 | 805 | "to get user callchain information. " |
---|
691 | 806 | "Falling back to framepointers.\n"); |
---|
692 | 807 | } else { |
---|
693 | | - perf_evsel__set_sample_bit(evsel, BRANCH_STACK); |
---|
| 808 | + evsel__set_sample_bit(evsel, BRANCH_STACK); |
---|
694 | 809 | attr->branch_sample_type = PERF_SAMPLE_BRANCH_USER | |
---|
695 | 810 | PERF_SAMPLE_BRANCH_CALL_STACK | |
---|
696 | 811 | PERF_SAMPLE_BRANCH_NO_CYCLES | |
---|
697 | | - PERF_SAMPLE_BRANCH_NO_FLAGS; |
---|
| 812 | + PERF_SAMPLE_BRANCH_NO_FLAGS | |
---|
| 813 | + PERF_SAMPLE_BRANCH_HW_INDEX; |
---|
698 | 814 | } |
---|
699 | 815 | } else |
---|
700 | 816 | pr_warning("Cannot use LBR callstack with branch stack. " |
---|
.. | .. |
---|
703 | 819 | |
---|
704 | 820 | if (param->record_mode == CALLCHAIN_DWARF) { |
---|
705 | 821 | if (!function) { |
---|
706 | | - perf_evsel__set_sample_bit(evsel, REGS_USER); |
---|
707 | | - perf_evsel__set_sample_bit(evsel, STACK_USER); |
---|
708 | | - attr->sample_regs_user |= PERF_REGS_MASK; |
---|
| 822 | + evsel__set_sample_bit(evsel, REGS_USER); |
---|
| 823 | + evsel__set_sample_bit(evsel, STACK_USER); |
---|
| 824 | + if (opts->sample_user_regs && DWARF_MINIMAL_REGS != PERF_REGS_MASK) { |
---|
| 825 | + attr->sample_regs_user |= DWARF_MINIMAL_REGS; |
---|
| 826 | + pr_warning("WARNING: The use of --call-graph=dwarf may require all the user registers, " |
---|
| 827 | + "specifying a subset with --user-regs may render DWARF unwinding unreliable, " |
---|
| 828 | + "so the minimal registers set (IP, SP) is explicitly forced.\n"); |
---|
| 829 | + } else { |
---|
| 830 | + attr->sample_regs_user |= PERF_REGS_MASK; |
---|
| 831 | + } |
---|
709 | 832 | attr->sample_stack_user = param->dump_size; |
---|
710 | 833 | attr->exclude_callchain_user = 1; |
---|
711 | 834 | } else { |
---|
.. | .. |
---|
720 | 843 | } |
---|
721 | 844 | } |
---|
722 | 845 | |
---|
723 | | -void perf_evsel__config_callchain(struct perf_evsel *evsel, |
---|
724 | | - struct record_opts *opts, |
---|
725 | | - struct callchain_param *param) |
---|
| 846 | +void evsel__config_callchain(struct evsel *evsel, struct record_opts *opts, |
---|
| 847 | + struct callchain_param *param) |
---|
726 | 848 | { |
---|
727 | 849 | if (param->enabled) |
---|
728 | | - return __perf_evsel__config_callchain(evsel, opts, param); |
---|
| 850 | + return __evsel__config_callchain(evsel, opts, param); |
---|
729 | 851 | } |
---|
730 | 852 | |
---|
731 | 853 | static void |
---|
732 | | -perf_evsel__reset_callgraph(struct perf_evsel *evsel, |
---|
| 854 | +perf_evsel__reset_callgraph(struct evsel *evsel, |
---|
733 | 855 | struct callchain_param *param) |
---|
734 | 856 | { |
---|
735 | | - struct perf_event_attr *attr = &evsel->attr; |
---|
| 857 | + struct perf_event_attr *attr = &evsel->core.attr; |
---|
736 | 858 | |
---|
737 | | - perf_evsel__reset_sample_bit(evsel, CALLCHAIN); |
---|
| 859 | + evsel__reset_sample_bit(evsel, CALLCHAIN); |
---|
738 | 860 | if (param->record_mode == CALLCHAIN_LBR) { |
---|
739 | | - perf_evsel__reset_sample_bit(evsel, BRANCH_STACK); |
---|
| 861 | + evsel__reset_sample_bit(evsel, BRANCH_STACK); |
---|
740 | 862 | attr->branch_sample_type &= ~(PERF_SAMPLE_BRANCH_USER | |
---|
741 | | - PERF_SAMPLE_BRANCH_CALL_STACK); |
---|
| 863 | + PERF_SAMPLE_BRANCH_CALL_STACK | |
---|
| 864 | + PERF_SAMPLE_BRANCH_HW_INDEX); |
---|
742 | 865 | } |
---|
743 | 866 | if (param->record_mode == CALLCHAIN_DWARF) { |
---|
744 | | - perf_evsel__reset_sample_bit(evsel, REGS_USER); |
---|
745 | | - perf_evsel__reset_sample_bit(evsel, STACK_USER); |
---|
| 867 | + evsel__reset_sample_bit(evsel, REGS_USER); |
---|
| 868 | + evsel__reset_sample_bit(evsel, STACK_USER); |
---|
746 | 869 | } |
---|
747 | 870 | } |
---|
748 | 871 | |
---|
749 | | -static void apply_config_terms(struct perf_evsel *evsel, |
---|
750 | | - struct record_opts *opts, bool track) |
---|
| 872 | +static void evsel__apply_config_terms(struct evsel *evsel, |
---|
| 873 | + struct record_opts *opts, bool track) |
---|
751 | 874 | { |
---|
752 | | - struct perf_evsel_config_term *term; |
---|
| 875 | + struct evsel_config_term *term; |
---|
753 | 876 | struct list_head *config_terms = &evsel->config_terms; |
---|
754 | | - struct perf_event_attr *attr = &evsel->attr; |
---|
| 877 | + struct perf_event_attr *attr = &evsel->core.attr; |
---|
755 | 878 | /* callgraph default */ |
---|
756 | 879 | struct callchain_param param = { |
---|
757 | 880 | .record_mode = callchain_param.record_mode, |
---|
.. | .. |
---|
762 | 885 | |
---|
763 | 886 | list_for_each_entry(term, config_terms, list) { |
---|
764 | 887 | switch (term->type) { |
---|
765 | | - case PERF_EVSEL__CONFIG_TERM_PERIOD: |
---|
| 888 | + case EVSEL__CONFIG_TERM_PERIOD: |
---|
766 | 889 | if (!(term->weak && opts->user_interval != ULLONG_MAX)) { |
---|
767 | 890 | attr->sample_period = term->val.period; |
---|
768 | 891 | attr->freq = 0; |
---|
769 | | - perf_evsel__reset_sample_bit(evsel, PERIOD); |
---|
| 892 | + evsel__reset_sample_bit(evsel, PERIOD); |
---|
770 | 893 | } |
---|
771 | 894 | break; |
---|
772 | | - case PERF_EVSEL__CONFIG_TERM_FREQ: |
---|
| 895 | + case EVSEL__CONFIG_TERM_FREQ: |
---|
773 | 896 | if (!(term->weak && opts->user_freq != UINT_MAX)) { |
---|
774 | 897 | attr->sample_freq = term->val.freq; |
---|
775 | 898 | attr->freq = 1; |
---|
776 | | - perf_evsel__set_sample_bit(evsel, PERIOD); |
---|
| 899 | + evsel__set_sample_bit(evsel, PERIOD); |
---|
777 | 900 | } |
---|
778 | 901 | break; |
---|
779 | | - case PERF_EVSEL__CONFIG_TERM_TIME: |
---|
| 902 | + case EVSEL__CONFIG_TERM_TIME: |
---|
780 | 903 | if (term->val.time) |
---|
781 | | - perf_evsel__set_sample_bit(evsel, TIME); |
---|
| 904 | + evsel__set_sample_bit(evsel, TIME); |
---|
782 | 905 | else |
---|
783 | | - perf_evsel__reset_sample_bit(evsel, TIME); |
---|
| 906 | + evsel__reset_sample_bit(evsel, TIME); |
---|
784 | 907 | break; |
---|
785 | | - case PERF_EVSEL__CONFIG_TERM_CALLGRAPH: |
---|
786 | | - callgraph_buf = term->val.callgraph; |
---|
| 908 | + case EVSEL__CONFIG_TERM_CALLGRAPH: |
---|
| 909 | + callgraph_buf = term->val.str; |
---|
787 | 910 | break; |
---|
788 | | - case PERF_EVSEL__CONFIG_TERM_BRANCH: |
---|
789 | | - if (term->val.branch && strcmp(term->val.branch, "no")) { |
---|
790 | | - perf_evsel__set_sample_bit(evsel, BRANCH_STACK); |
---|
791 | | - parse_branch_str(term->val.branch, |
---|
| 911 | + case EVSEL__CONFIG_TERM_BRANCH: |
---|
| 912 | + if (term->val.str && strcmp(term->val.str, "no")) { |
---|
| 913 | + evsel__set_sample_bit(evsel, BRANCH_STACK); |
---|
| 914 | + parse_branch_str(term->val.str, |
---|
792 | 915 | &attr->branch_sample_type); |
---|
793 | 916 | } else |
---|
794 | | - perf_evsel__reset_sample_bit(evsel, BRANCH_STACK); |
---|
| 917 | + evsel__reset_sample_bit(evsel, BRANCH_STACK); |
---|
795 | 918 | break; |
---|
796 | | - case PERF_EVSEL__CONFIG_TERM_STACK_USER: |
---|
| 919 | + case EVSEL__CONFIG_TERM_STACK_USER: |
---|
797 | 920 | dump_size = term->val.stack_user; |
---|
798 | 921 | break; |
---|
799 | | - case PERF_EVSEL__CONFIG_TERM_MAX_STACK: |
---|
| 922 | + case EVSEL__CONFIG_TERM_MAX_STACK: |
---|
800 | 923 | max_stack = term->val.max_stack; |
---|
801 | 924 | break; |
---|
802 | | - case PERF_EVSEL__CONFIG_TERM_INHERIT: |
---|
| 925 | + case EVSEL__CONFIG_TERM_MAX_EVENTS: |
---|
| 926 | + evsel->max_events = term->val.max_events; |
---|
| 927 | + break; |
---|
| 928 | + case EVSEL__CONFIG_TERM_INHERIT: |
---|
803 | 929 | /* |
---|
804 | 930 | * attr->inherit should has already been set by |
---|
805 | | - * perf_evsel__config. If user explicitly set |
---|
| 931 | + * evsel__config. If user explicitly set |
---|
806 | 932 | * inherit using config terms, override global |
---|
807 | 933 | * opt->no_inherit setting. |
---|
808 | 934 | */ |
---|
809 | 935 | attr->inherit = term->val.inherit ? 1 : 0; |
---|
810 | 936 | break; |
---|
811 | | - case PERF_EVSEL__CONFIG_TERM_OVERWRITE: |
---|
| 937 | + case EVSEL__CONFIG_TERM_OVERWRITE: |
---|
812 | 938 | attr->write_backward = term->val.overwrite ? 1 : 0; |
---|
813 | 939 | break; |
---|
814 | | - case PERF_EVSEL__CONFIG_TERM_DRV_CFG: |
---|
| 940 | + case EVSEL__CONFIG_TERM_DRV_CFG: |
---|
| 941 | + break; |
---|
| 942 | + case EVSEL__CONFIG_TERM_PERCORE: |
---|
| 943 | + break; |
---|
| 944 | + case EVSEL__CONFIG_TERM_AUX_OUTPUT: |
---|
| 945 | + attr->aux_output = term->val.aux_output ? 1 : 0; |
---|
| 946 | + break; |
---|
| 947 | + case EVSEL__CONFIG_TERM_AUX_SAMPLE_SIZE: |
---|
| 948 | + /* Already applied by auxtrace */ |
---|
| 949 | + break; |
---|
| 950 | + case EVSEL__CONFIG_TERM_CFG_CHG: |
---|
815 | 951 | break; |
---|
816 | 952 | default: |
---|
817 | 953 | break; |
---|
.. | .. |
---|
857 | 993 | /* set perf-event callgraph */ |
---|
858 | 994 | if (param.enabled) { |
---|
859 | 995 | if (sample_address) { |
---|
860 | | - perf_evsel__set_sample_bit(evsel, ADDR); |
---|
861 | | - perf_evsel__set_sample_bit(evsel, DATA_SRC); |
---|
862 | | - evsel->attr.mmap_data = track; |
---|
| 996 | + evsel__set_sample_bit(evsel, ADDR); |
---|
| 997 | + evsel__set_sample_bit(evsel, DATA_SRC); |
---|
| 998 | + evsel->core.attr.mmap_data = track; |
---|
863 | 999 | } |
---|
864 | | - perf_evsel__config_callchain(evsel, opts, ¶m); |
---|
| 1000 | + evsel__config_callchain(evsel, opts, ¶m); |
---|
865 | 1001 | } |
---|
866 | 1002 | } |
---|
867 | 1003 | } |
---|
868 | 1004 | |
---|
869 | | -static bool is_dummy_event(struct perf_evsel *evsel) |
---|
| 1005 | +struct evsel_config_term *__evsel__get_config_term(struct evsel *evsel, enum evsel_term_type type) |
---|
870 | 1006 | { |
---|
871 | | - return (evsel->attr.type == PERF_TYPE_SOFTWARE) && |
---|
872 | | - (evsel->attr.config == PERF_COUNT_SW_DUMMY); |
---|
| 1007 | + struct evsel_config_term *term, *found_term = NULL; |
---|
| 1008 | + |
---|
| 1009 | + list_for_each_entry(term, &evsel->config_terms, list) { |
---|
| 1010 | + if (term->type == type) |
---|
| 1011 | + found_term = term; |
---|
| 1012 | + } |
---|
| 1013 | + |
---|
| 1014 | + return found_term; |
---|
| 1015 | +} |
---|
| 1016 | + |
---|
| 1017 | +static void evsel__set_default_freq_period(struct record_opts *opts, |
---|
| 1018 | + struct perf_event_attr *attr) |
---|
| 1019 | +{ |
---|
| 1020 | + if (opts->freq) { |
---|
| 1021 | + attr->freq = 1; |
---|
| 1022 | + attr->sample_freq = opts->freq; |
---|
| 1023 | + } else { |
---|
| 1024 | + attr->sample_period = opts->default_interval; |
---|
| 1025 | + } |
---|
873 | 1026 | } |
---|
874 | 1027 | |
---|
875 | 1028 | /* |
---|
.. | .. |
---|
900 | 1053 | * enable/disable events specifically, as there's no |
---|
901 | 1054 | * initial traced exec call. |
---|
902 | 1055 | */ |
---|
903 | | -void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts, |
---|
904 | | - struct callchain_param *callchain) |
---|
| 1056 | +void evsel__config(struct evsel *evsel, struct record_opts *opts, |
---|
| 1057 | + struct callchain_param *callchain) |
---|
905 | 1058 | { |
---|
906 | | - struct perf_evsel *leader = evsel->leader; |
---|
907 | | - struct perf_event_attr *attr = &evsel->attr; |
---|
| 1059 | + struct evsel *leader = evsel->leader; |
---|
| 1060 | + struct perf_event_attr *attr = &evsel->core.attr; |
---|
908 | 1061 | int track = evsel->tracking; |
---|
909 | 1062 | bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread; |
---|
910 | 1063 | |
---|
.. | .. |
---|
912 | 1065 | attr->inherit = !opts->no_inherit; |
---|
913 | 1066 | attr->write_backward = opts->overwrite ? 1 : 0; |
---|
914 | 1067 | |
---|
915 | | - perf_evsel__set_sample_bit(evsel, IP); |
---|
916 | | - perf_evsel__set_sample_bit(evsel, TID); |
---|
| 1068 | + evsel__set_sample_bit(evsel, IP); |
---|
| 1069 | + evsel__set_sample_bit(evsel, TID); |
---|
917 | 1070 | |
---|
918 | 1071 | if (evsel->sample_read) { |
---|
919 | | - perf_evsel__set_sample_bit(evsel, READ); |
---|
| 1072 | + evsel__set_sample_bit(evsel, READ); |
---|
920 | 1073 | |
---|
921 | 1074 | /* |
---|
922 | 1075 | * We need ID even in case of single event, because |
---|
923 | 1076 | * PERF_SAMPLE_READ process ID specific data. |
---|
924 | 1077 | */ |
---|
925 | | - perf_evsel__set_sample_id(evsel, false); |
---|
| 1078 | + evsel__set_sample_id(evsel, false); |
---|
926 | 1079 | |
---|
927 | 1080 | /* |
---|
928 | 1081 | * Apply group format only if we belong to group |
---|
929 | 1082 | * with more than one members. |
---|
930 | 1083 | */ |
---|
931 | | - if (leader->nr_members > 1) { |
---|
| 1084 | + if (leader->core.nr_members > 1) { |
---|
932 | 1085 | attr->read_format |= PERF_FORMAT_GROUP; |
---|
933 | 1086 | attr->inherit = 0; |
---|
934 | 1087 | } |
---|
.. | .. |
---|
938 | 1091 | * We default some events to have a default interval. But keep |
---|
939 | 1092 | * it a weak assumption overridable by the user. |
---|
940 | 1093 | */ |
---|
941 | | - if (!attr->sample_period || (opts->user_freq != UINT_MAX || |
---|
942 | | - opts->user_interval != ULLONG_MAX)) { |
---|
943 | | - if (opts->freq) { |
---|
944 | | - perf_evsel__set_sample_bit(evsel, PERIOD); |
---|
945 | | - attr->freq = 1; |
---|
946 | | - attr->sample_freq = opts->freq; |
---|
947 | | - } else { |
---|
948 | | - attr->sample_period = opts->default_interval; |
---|
949 | | - } |
---|
950 | | - } |
---|
| 1094 | + if ((evsel->is_libpfm_event && !attr->sample_period) || |
---|
| 1095 | + (!evsel->is_libpfm_event && (!attr->sample_period || |
---|
| 1096 | + opts->user_freq != UINT_MAX || |
---|
| 1097 | + opts->user_interval != ULLONG_MAX))) |
---|
| 1098 | + evsel__set_default_freq_period(opts, attr); |
---|
951 | 1099 | |
---|
952 | 1100 | /* |
---|
953 | | - * Disable sampling for all group members other |
---|
954 | | - * than leader in case leader 'leads' the sampling. |
---|
| 1101 | + * If attr->freq was set (here or earlier), ask for period |
---|
| 1102 | + * to be sampled. |
---|
955 | 1103 | */ |
---|
956 | | - if ((leader != evsel) && leader->sample_read) { |
---|
957 | | - attr->freq = 0; |
---|
958 | | - attr->sample_freq = 0; |
---|
959 | | - attr->sample_period = 0; |
---|
960 | | - attr->write_backward = 0; |
---|
961 | | - } |
---|
| 1104 | + if (attr->freq) |
---|
| 1105 | + evsel__set_sample_bit(evsel, PERIOD); |
---|
962 | 1106 | |
---|
963 | 1107 | if (opts->no_samples) |
---|
964 | 1108 | attr->sample_freq = 0; |
---|
965 | 1109 | |
---|
966 | 1110 | if (opts->inherit_stat) { |
---|
967 | | - evsel->attr.read_format |= |
---|
| 1111 | + evsel->core.attr.read_format |= |
---|
968 | 1112 | PERF_FORMAT_TOTAL_TIME_ENABLED | |
---|
969 | 1113 | PERF_FORMAT_TOTAL_TIME_RUNNING | |
---|
970 | 1114 | PERF_FORMAT_ID; |
---|
.. | .. |
---|
972 | 1116 | } |
---|
973 | 1117 | |
---|
974 | 1118 | if (opts->sample_address) { |
---|
975 | | - perf_evsel__set_sample_bit(evsel, ADDR); |
---|
| 1119 | + evsel__set_sample_bit(evsel, ADDR); |
---|
976 | 1120 | attr->mmap_data = track; |
---|
977 | 1121 | } |
---|
978 | 1122 | |
---|
.. | .. |
---|
981 | 1125 | * event, due to issues with page faults while tracing page |
---|
982 | 1126 | * fault handler and its overall trickiness nature. |
---|
983 | 1127 | */ |
---|
984 | | - if (perf_evsel__is_function_event(evsel)) |
---|
985 | | - evsel->attr.exclude_callchain_user = 1; |
---|
| 1128 | + if (evsel__is_function_event(evsel)) |
---|
| 1129 | + evsel->core.attr.exclude_callchain_user = 1; |
---|
986 | 1130 | |
---|
987 | 1131 | if (callchain && callchain->enabled && !evsel->no_aux_samples) |
---|
988 | | - perf_evsel__config_callchain(evsel, opts, callchain); |
---|
| 1132 | + evsel__config_callchain(evsel, opts, callchain); |
---|
989 | 1133 | |
---|
990 | | - if (opts->sample_intr_regs) { |
---|
| 1134 | + if (opts->sample_intr_regs && !evsel->no_aux_samples && |
---|
| 1135 | + !evsel__is_dummy_event(evsel)) { |
---|
991 | 1136 | attr->sample_regs_intr = opts->sample_intr_regs; |
---|
992 | | - perf_evsel__set_sample_bit(evsel, REGS_INTR); |
---|
| 1137 | + evsel__set_sample_bit(evsel, REGS_INTR); |
---|
993 | 1138 | } |
---|
994 | 1139 | |
---|
995 | | - if (opts->sample_user_regs) { |
---|
| 1140 | + if (opts->sample_user_regs && !evsel->no_aux_samples && |
---|
| 1141 | + !evsel__is_dummy_event(evsel)) { |
---|
996 | 1142 | attr->sample_regs_user |= opts->sample_user_regs; |
---|
997 | | - perf_evsel__set_sample_bit(evsel, REGS_USER); |
---|
| 1143 | + evsel__set_sample_bit(evsel, REGS_USER); |
---|
998 | 1144 | } |
---|
999 | 1145 | |
---|
1000 | 1146 | if (target__has_cpu(&opts->target) || opts->sample_cpu) |
---|
1001 | | - perf_evsel__set_sample_bit(evsel, CPU); |
---|
| 1147 | + evsel__set_sample_bit(evsel, CPU); |
---|
1002 | 1148 | |
---|
1003 | 1149 | /* |
---|
1004 | 1150 | * When the user explicitly disabled time don't force it here. |
---|
.. | .. |
---|
1007 | 1153 | (!perf_missing_features.sample_id_all && |
---|
1008 | 1154 | (!opts->no_inherit || target__has_cpu(&opts->target) || per_cpu || |
---|
1009 | 1155 | opts->sample_time_set))) |
---|
1010 | | - perf_evsel__set_sample_bit(evsel, TIME); |
---|
| 1156 | + evsel__set_sample_bit(evsel, TIME); |
---|
1011 | 1157 | |
---|
1012 | 1158 | if (opts->raw_samples && !evsel->no_aux_samples) { |
---|
1013 | | - perf_evsel__set_sample_bit(evsel, TIME); |
---|
1014 | | - perf_evsel__set_sample_bit(evsel, RAW); |
---|
1015 | | - perf_evsel__set_sample_bit(evsel, CPU); |
---|
| 1159 | + evsel__set_sample_bit(evsel, TIME); |
---|
| 1160 | + evsel__set_sample_bit(evsel, RAW); |
---|
| 1161 | + evsel__set_sample_bit(evsel, CPU); |
---|
1016 | 1162 | } |
---|
1017 | 1163 | |
---|
1018 | 1164 | if (opts->sample_address) |
---|
1019 | | - perf_evsel__set_sample_bit(evsel, DATA_SRC); |
---|
| 1165 | + evsel__set_sample_bit(evsel, DATA_SRC); |
---|
1020 | 1166 | |
---|
1021 | 1167 | if (opts->sample_phys_addr) |
---|
1022 | | - perf_evsel__set_sample_bit(evsel, PHYS_ADDR); |
---|
| 1168 | + evsel__set_sample_bit(evsel, PHYS_ADDR); |
---|
1023 | 1169 | |
---|
1024 | 1170 | if (opts->no_buffering) { |
---|
1025 | 1171 | attr->watermark = 0; |
---|
1026 | 1172 | attr->wakeup_events = 1; |
---|
1027 | 1173 | } |
---|
1028 | 1174 | if (opts->branch_stack && !evsel->no_aux_samples) { |
---|
1029 | | - perf_evsel__set_sample_bit(evsel, BRANCH_STACK); |
---|
| 1175 | + evsel__set_sample_bit(evsel, BRANCH_STACK); |
---|
1030 | 1176 | attr->branch_sample_type = opts->branch_stack; |
---|
1031 | 1177 | } |
---|
1032 | 1178 | |
---|
1033 | 1179 | if (opts->sample_weight) |
---|
1034 | | - perf_evsel__set_sample_bit(evsel, WEIGHT); |
---|
| 1180 | + evsel__set_sample_bit(evsel, WEIGHT); |
---|
1035 | 1181 | |
---|
1036 | 1182 | attr->task = track; |
---|
1037 | 1183 | attr->mmap = track; |
---|
1038 | 1184 | attr->mmap2 = track && !perf_missing_features.mmap2; |
---|
1039 | 1185 | attr->comm = track; |
---|
| 1186 | + /* |
---|
| 1187 | + * ksymbol is tracked separately with text poke because it needs to be |
---|
| 1188 | + * system wide and enabled immediately. |
---|
| 1189 | + */ |
---|
| 1190 | + if (!opts->text_poke) |
---|
| 1191 | + attr->ksymbol = track && !perf_missing_features.ksymbol; |
---|
| 1192 | + attr->bpf_event = track && !opts->no_bpf_event && !perf_missing_features.bpf; |
---|
1040 | 1193 | |
---|
1041 | 1194 | if (opts->record_namespaces) |
---|
1042 | 1195 | attr->namespaces = track; |
---|
| 1196 | + |
---|
| 1197 | + if (opts->record_cgroup) { |
---|
| 1198 | + attr->cgroup = track && !perf_missing_features.cgroup; |
---|
| 1199 | + evsel__set_sample_bit(evsel, CGROUP); |
---|
| 1200 | + } |
---|
1043 | 1201 | |
---|
1044 | 1202 | if (opts->record_switch_events) |
---|
1045 | 1203 | attr->context_switch = track; |
---|
1046 | 1204 | |
---|
1047 | 1205 | if (opts->sample_transaction) |
---|
1048 | | - perf_evsel__set_sample_bit(evsel, TRANSACTION); |
---|
| 1206 | + evsel__set_sample_bit(evsel, TRANSACTION); |
---|
1049 | 1207 | |
---|
1050 | 1208 | if (opts->running_time) { |
---|
1051 | | - evsel->attr.read_format |= |
---|
| 1209 | + evsel->core.attr.read_format |= |
---|
1052 | 1210 | PERF_FORMAT_TOTAL_TIME_ENABLED | |
---|
1053 | 1211 | PERF_FORMAT_TOTAL_TIME_RUNNING; |
---|
1054 | 1212 | } |
---|
.. | .. |
---|
1059 | 1217 | * Disabling only independent events or group leaders, |
---|
1060 | 1218 | * keeping group members enabled. |
---|
1061 | 1219 | */ |
---|
1062 | | - if (perf_evsel__is_group_leader(evsel)) |
---|
| 1220 | + if (evsel__is_group_leader(evsel)) |
---|
1063 | 1221 | attr->disabled = 1; |
---|
1064 | 1222 | |
---|
1065 | 1223 | /* |
---|
1066 | 1224 | * Setting enable_on_exec for independent events and |
---|
1067 | 1225 | * group leaders for traced executed by perf. |
---|
1068 | 1226 | */ |
---|
1069 | | - if (target__none(&opts->target) && perf_evsel__is_group_leader(evsel) && |
---|
1070 | | - !opts->initial_delay) |
---|
| 1227 | + if (target__none(&opts->target) && evsel__is_group_leader(evsel) && |
---|
| 1228 | + !opts->initial_delay) |
---|
1071 | 1229 | attr->enable_on_exec = 1; |
---|
1072 | 1230 | |
---|
1073 | 1231 | if (evsel->immediate) { |
---|
.. | .. |
---|
1082 | 1240 | } |
---|
1083 | 1241 | |
---|
1084 | 1242 | if (evsel->precise_max) |
---|
1085 | | - perf_event_attr__set_max_precise_ip(attr); |
---|
| 1243 | + attr->precise_ip = 3; |
---|
1086 | 1244 | |
---|
1087 | 1245 | if (opts->all_user) { |
---|
1088 | 1246 | attr->exclude_kernel = 1; |
---|
.. | .. |
---|
1094 | 1252 | attr->exclude_user = 1; |
---|
1095 | 1253 | } |
---|
1096 | 1254 | |
---|
1097 | | - if (evsel->own_cpus || evsel->unit) |
---|
1098 | | - evsel->attr.read_format |= PERF_FORMAT_ID; |
---|
| 1255 | + if (evsel->core.own_cpus || evsel->unit) |
---|
| 1256 | + evsel->core.attr.read_format |= PERF_FORMAT_ID; |
---|
1099 | 1257 | |
---|
1100 | 1258 | /* |
---|
1101 | 1259 | * Apply event specific term settings, |
---|
1102 | 1260 | * it overloads any global configuration. |
---|
1103 | 1261 | */ |
---|
1104 | | - apply_config_terms(evsel, opts, track); |
---|
| 1262 | + evsel__apply_config_terms(evsel, opts, track); |
---|
1105 | 1263 | |
---|
1106 | 1264 | evsel->ignore_missing_thread = opts->ignore_missing_thread; |
---|
1107 | 1265 | |
---|
1108 | 1266 | /* The --period option takes the precedence. */ |
---|
1109 | 1267 | if (opts->period_set) { |
---|
1110 | 1268 | if (opts->period) |
---|
1111 | | - perf_evsel__set_sample_bit(evsel, PERIOD); |
---|
| 1269 | + evsel__set_sample_bit(evsel, PERIOD); |
---|
1112 | 1270 | else |
---|
1113 | | - perf_evsel__reset_sample_bit(evsel, PERIOD); |
---|
| 1271 | + evsel__reset_sample_bit(evsel, PERIOD); |
---|
1114 | 1272 | } |
---|
1115 | 1273 | |
---|
1116 | 1274 | /* |
---|
| 1275 | + * A dummy event never triggers any actual counter and therefore |
---|
| 1276 | + * cannot be used with branch_stack. |
---|
| 1277 | + * |
---|
1117 | 1278 | * For initial_delay, a dummy event is added implicitly. |
---|
1118 | 1279 | * The software event will trigger -EOPNOTSUPP error out, |
---|
1119 | 1280 | * if BRANCH_STACK bit is set. |
---|
1120 | 1281 | */ |
---|
1121 | | - if (opts->initial_delay && is_dummy_event(evsel)) |
---|
1122 | | - perf_evsel__reset_sample_bit(evsel, BRANCH_STACK); |
---|
| 1282 | + if (evsel__is_dummy_event(evsel)) |
---|
| 1283 | + evsel__reset_sample_bit(evsel, BRANCH_STACK); |
---|
1123 | 1284 | } |
---|
1124 | 1285 | |
---|
1125 | | -static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) |
---|
1126 | | -{ |
---|
1127 | | - if (evsel->system_wide) |
---|
1128 | | - nthreads = 1; |
---|
1129 | | - |
---|
1130 | | - evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); |
---|
1131 | | - |
---|
1132 | | - if (evsel->fd) { |
---|
1133 | | - int cpu, thread; |
---|
1134 | | - for (cpu = 0; cpu < ncpus; cpu++) { |
---|
1135 | | - for (thread = 0; thread < nthreads; thread++) { |
---|
1136 | | - FD(evsel, cpu, thread) = -1; |
---|
1137 | | - } |
---|
1138 | | - } |
---|
1139 | | - } |
---|
1140 | | - |
---|
1141 | | - return evsel->fd != NULL ? 0 : -ENOMEM; |
---|
1142 | | -} |
---|
1143 | | - |
---|
1144 | | -static int perf_evsel__run_ioctl(struct perf_evsel *evsel, |
---|
1145 | | - int ioc, void *arg) |
---|
1146 | | -{ |
---|
1147 | | - int cpu, thread; |
---|
1148 | | - |
---|
1149 | | - for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) { |
---|
1150 | | - for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { |
---|
1151 | | - int fd = FD(evsel, cpu, thread), |
---|
1152 | | - err = ioctl(fd, ioc, arg); |
---|
1153 | | - |
---|
1154 | | - if (err) |
---|
1155 | | - return err; |
---|
1156 | | - } |
---|
1157 | | - } |
---|
1158 | | - |
---|
1159 | | - return 0; |
---|
1160 | | -} |
---|
1161 | | - |
---|
1162 | | -int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter) |
---|
1163 | | -{ |
---|
1164 | | - return perf_evsel__run_ioctl(evsel, |
---|
1165 | | - PERF_EVENT_IOC_SET_FILTER, |
---|
1166 | | - (void *)filter); |
---|
1167 | | -} |
---|
1168 | | - |
---|
1169 | | -int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter) |
---|
| 1286 | +int evsel__set_filter(struct evsel *evsel, const char *filter) |
---|
1170 | 1287 | { |
---|
1171 | 1288 | char *new_filter = strdup(filter); |
---|
1172 | 1289 | |
---|
.. | .. |
---|
1179 | 1296 | return -1; |
---|
1180 | 1297 | } |
---|
1181 | 1298 | |
---|
1182 | | -static int perf_evsel__append_filter(struct perf_evsel *evsel, |
---|
1183 | | - const char *fmt, const char *filter) |
---|
| 1299 | +static int evsel__append_filter(struct evsel *evsel, const char *fmt, const char *filter) |
---|
1184 | 1300 | { |
---|
1185 | 1301 | char *new_filter; |
---|
1186 | 1302 | |
---|
1187 | 1303 | if (evsel->filter == NULL) |
---|
1188 | | - return perf_evsel__set_filter(evsel, filter); |
---|
| 1304 | + return evsel__set_filter(evsel, filter); |
---|
1189 | 1305 | |
---|
1190 | 1306 | if (asprintf(&new_filter, fmt, evsel->filter, filter) > 0) { |
---|
1191 | 1307 | free(evsel->filter); |
---|
.. | .. |
---|
1196 | 1312 | return -1; |
---|
1197 | 1313 | } |
---|
1198 | 1314 | |
---|
1199 | | -int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter) |
---|
| 1315 | +int evsel__append_tp_filter(struct evsel *evsel, const char *filter) |
---|
1200 | 1316 | { |
---|
1201 | | - return perf_evsel__append_filter(evsel, "(%s) && (%s)", filter); |
---|
| 1317 | + return evsel__append_filter(evsel, "(%s) && (%s)", filter); |
---|
1202 | 1318 | } |
---|
1203 | 1319 | |
---|
1204 | | -int perf_evsel__append_addr_filter(struct perf_evsel *evsel, const char *filter) |
---|
| 1320 | +int evsel__append_addr_filter(struct evsel *evsel, const char *filter) |
---|
1205 | 1321 | { |
---|
1206 | | - return perf_evsel__append_filter(evsel, "%s,%s", filter); |
---|
| 1322 | + return evsel__append_filter(evsel, "%s,%s", filter); |
---|
1207 | 1323 | } |
---|
1208 | 1324 | |
---|
1209 | | -int perf_evsel__enable(struct perf_evsel *evsel) |
---|
| 1325 | +/* Caller has to clear disabled after going through all CPUs. */ |
---|
| 1326 | +int evsel__enable_cpu(struct evsel *evsel, int cpu) |
---|
1210 | 1327 | { |
---|
1211 | | - return perf_evsel__run_ioctl(evsel, |
---|
1212 | | - PERF_EVENT_IOC_ENABLE, |
---|
1213 | | - 0); |
---|
| 1328 | + return perf_evsel__enable_cpu(&evsel->core, cpu); |
---|
1214 | 1329 | } |
---|
1215 | 1330 | |
---|
1216 | | -int perf_evsel__disable(struct perf_evsel *evsel) |
---|
| 1331 | +int evsel__enable(struct evsel *evsel) |
---|
1217 | 1332 | { |
---|
1218 | | - return perf_evsel__run_ioctl(evsel, |
---|
1219 | | - PERF_EVENT_IOC_DISABLE, |
---|
1220 | | - 0); |
---|
| 1333 | + int err = perf_evsel__enable(&evsel->core); |
---|
| 1334 | + |
---|
| 1335 | + if (!err) |
---|
| 1336 | + evsel->disabled = false; |
---|
| 1337 | + return err; |
---|
1221 | 1338 | } |
---|
1222 | 1339 | |
---|
1223 | | -int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) |
---|
| 1340 | +/* Caller has to set disabled after going through all CPUs. */ |
---|
| 1341 | +int evsel__disable_cpu(struct evsel *evsel, int cpu) |
---|
1224 | 1342 | { |
---|
1225 | | - if (ncpus == 0 || nthreads == 0) |
---|
1226 | | - return 0; |
---|
1227 | | - |
---|
1228 | | - if (evsel->system_wide) |
---|
1229 | | - nthreads = 1; |
---|
1230 | | - |
---|
1231 | | - evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); |
---|
1232 | | - if (evsel->sample_id == NULL) |
---|
1233 | | - return -ENOMEM; |
---|
1234 | | - |
---|
1235 | | - evsel->id = zalloc(ncpus * nthreads * sizeof(u64)); |
---|
1236 | | - if (evsel->id == NULL) { |
---|
1237 | | - xyarray__delete(evsel->sample_id); |
---|
1238 | | - evsel->sample_id = NULL; |
---|
1239 | | - return -ENOMEM; |
---|
1240 | | - } |
---|
1241 | | - |
---|
1242 | | - return 0; |
---|
| 1343 | + return perf_evsel__disable_cpu(&evsel->core, cpu); |
---|
1243 | 1344 | } |
---|
1244 | 1345 | |
---|
1245 | | -static void perf_evsel__free_fd(struct perf_evsel *evsel) |
---|
| 1346 | +int evsel__disable(struct evsel *evsel) |
---|
1246 | 1347 | { |
---|
1247 | | - xyarray__delete(evsel->fd); |
---|
1248 | | - evsel->fd = NULL; |
---|
| 1348 | + int err = perf_evsel__disable(&evsel->core); |
---|
| 1349 | + /* |
---|
| 1350 | + * We mark it disabled here so that tools that disable a event can |
---|
| 1351 | + * ignore events after they disable it. I.e. the ring buffer may have |
---|
| 1352 | + * already a few more events queued up before the kernel got the stop |
---|
| 1353 | + * request. |
---|
| 1354 | + */ |
---|
| 1355 | + if (!err) |
---|
| 1356 | + evsel->disabled = true; |
---|
| 1357 | + |
---|
| 1358 | + return err; |
---|
1249 | 1359 | } |
---|
1250 | 1360 | |
---|
1251 | | -static void perf_evsel__free_id(struct perf_evsel *evsel) |
---|
| 1361 | +static void evsel__free_config_terms(struct evsel *evsel) |
---|
1252 | 1362 | { |
---|
1253 | | - xyarray__delete(evsel->sample_id); |
---|
1254 | | - evsel->sample_id = NULL; |
---|
1255 | | - zfree(&evsel->id); |
---|
1256 | | -} |
---|
1257 | | - |
---|
1258 | | -static void perf_evsel__free_config_terms(struct perf_evsel *evsel) |
---|
1259 | | -{ |
---|
1260 | | - struct perf_evsel_config_term *term, *h; |
---|
| 1363 | + struct evsel_config_term *term, *h; |
---|
1261 | 1364 | |
---|
1262 | 1365 | list_for_each_entry_safe(term, h, &evsel->config_terms, list) { |
---|
1263 | | - list_del(&term->list); |
---|
| 1366 | + list_del_init(&term->list); |
---|
| 1367 | + if (term->free_str) |
---|
| 1368 | + zfree(&term->val.str); |
---|
1264 | 1369 | free(term); |
---|
1265 | 1370 | } |
---|
1266 | 1371 | } |
---|
1267 | 1372 | |
---|
1268 | | -void perf_evsel__close_fd(struct perf_evsel *evsel) |
---|
| 1373 | +void evsel__exit(struct evsel *evsel) |
---|
1269 | 1374 | { |
---|
1270 | | - int cpu, thread; |
---|
1271 | | - |
---|
1272 | | - for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) |
---|
1273 | | - for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) { |
---|
1274 | | - close(FD(evsel, cpu, thread)); |
---|
1275 | | - FD(evsel, cpu, thread) = -1; |
---|
1276 | | - } |
---|
1277 | | -} |
---|
1278 | | - |
---|
1279 | | -void perf_evsel__exit(struct perf_evsel *evsel) |
---|
1280 | | -{ |
---|
1281 | | - assert(list_empty(&evsel->node)); |
---|
| 1375 | + assert(list_empty(&evsel->core.node)); |
---|
1282 | 1376 | assert(evsel->evlist == NULL); |
---|
1283 | | - perf_evsel__free_counts(evsel); |
---|
1284 | | - perf_evsel__free_fd(evsel); |
---|
1285 | | - perf_evsel__free_id(evsel); |
---|
1286 | | - perf_evsel__free_config_terms(evsel); |
---|
| 1377 | + evsel__free_counts(evsel); |
---|
| 1378 | + perf_evsel__free_fd(&evsel->core); |
---|
| 1379 | + perf_evsel__free_id(&evsel->core); |
---|
| 1380 | + evsel__free_config_terms(evsel); |
---|
1287 | 1381 | cgroup__put(evsel->cgrp); |
---|
1288 | | - cpu_map__put(evsel->cpus); |
---|
1289 | | - cpu_map__put(evsel->own_cpus); |
---|
1290 | | - thread_map__put(evsel->threads); |
---|
| 1382 | + perf_cpu_map__put(evsel->core.cpus); |
---|
| 1383 | + perf_cpu_map__put(evsel->core.own_cpus); |
---|
| 1384 | + perf_thread_map__put(evsel->core.threads); |
---|
1291 | 1385 | zfree(&evsel->group_name); |
---|
1292 | 1386 | zfree(&evsel->name); |
---|
1293 | 1387 | zfree(&evsel->pmu_name); |
---|
.. | .. |
---|
1296 | 1390 | perf_evsel__object.fini(evsel); |
---|
1297 | 1391 | } |
---|
1298 | 1392 | |
---|
1299 | | -void perf_evsel__delete(struct perf_evsel *evsel) |
---|
| 1393 | +void evsel__delete(struct evsel *evsel) |
---|
1300 | 1394 | { |
---|
1301 | | - perf_evsel__exit(evsel); |
---|
| 1395 | + evsel__exit(evsel); |
---|
1302 | 1396 | free(evsel); |
---|
1303 | 1397 | } |
---|
1304 | 1398 | |
---|
1305 | | -void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, int thread, |
---|
1306 | | - struct perf_counts_values *count) |
---|
| 1399 | +void evsel__compute_deltas(struct evsel *evsel, int cpu, int thread, |
---|
| 1400 | + struct perf_counts_values *count) |
---|
1307 | 1401 | { |
---|
1308 | 1402 | struct perf_counts_values tmp; |
---|
1309 | 1403 | |
---|
.. | .. |
---|
1334 | 1428 | count->val = 0; |
---|
1335 | 1429 | } else if (count->run < count->ena) { |
---|
1336 | 1430 | scaled = 1; |
---|
1337 | | - count->val = (u64)((double) count->val * count->ena / count->run + 0.5); |
---|
| 1431 | + count->val = (u64)((double) count->val * count->ena / count->run); |
---|
1338 | 1432 | } |
---|
1339 | | - } else |
---|
1340 | | - count->ena = count->run = 0; |
---|
| 1433 | + } |
---|
1341 | 1434 | |
---|
1342 | 1435 | if (pscaled) |
---|
1343 | 1436 | *pscaled = scaled; |
---|
1344 | 1437 | } |
---|
1345 | 1438 | |
---|
1346 | | -static int perf_evsel__read_size(struct perf_evsel *evsel) |
---|
1347 | | -{ |
---|
1348 | | - u64 read_format = evsel->attr.read_format; |
---|
1349 | | - int entry = sizeof(u64); /* value */ |
---|
1350 | | - int size = 0; |
---|
1351 | | - int nr = 1; |
---|
1352 | | - |
---|
1353 | | - if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) |
---|
1354 | | - size += sizeof(u64); |
---|
1355 | | - |
---|
1356 | | - if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) |
---|
1357 | | - size += sizeof(u64); |
---|
1358 | | - |
---|
1359 | | - if (read_format & PERF_FORMAT_ID) |
---|
1360 | | - entry += sizeof(u64); |
---|
1361 | | - |
---|
1362 | | - if (read_format & PERF_FORMAT_GROUP) { |
---|
1363 | | - nr = evsel->nr_members; |
---|
1364 | | - size += sizeof(u64); |
---|
1365 | | - } |
---|
1366 | | - |
---|
1367 | | - size += entry * nr; |
---|
1368 | | - return size; |
---|
1369 | | -} |
---|
1370 | | - |
---|
1371 | | -int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, |
---|
1372 | | - struct perf_counts_values *count) |
---|
1373 | | -{ |
---|
1374 | | - size_t size = perf_evsel__read_size(evsel); |
---|
1375 | | - |
---|
1376 | | - memset(count, 0, sizeof(*count)); |
---|
1377 | | - |
---|
1378 | | - if (FD(evsel, cpu, thread) < 0) |
---|
1379 | | - return -EINVAL; |
---|
1380 | | - |
---|
1381 | | - if (readn(FD(evsel, cpu, thread), count->values, size) <= 0) |
---|
1382 | | - return -errno; |
---|
1383 | | - |
---|
1384 | | - return 0; |
---|
1385 | | -} |
---|
1386 | | - |
---|
1387 | | -static int |
---|
1388 | | -perf_evsel__read_one(struct perf_evsel *evsel, int cpu, int thread) |
---|
| 1439 | +static int evsel__read_one(struct evsel *evsel, int cpu, int thread) |
---|
1389 | 1440 | { |
---|
1390 | 1441 | struct perf_counts_values *count = perf_counts(evsel->counts, cpu, thread); |
---|
1391 | 1442 | |
---|
1392 | | - return perf_evsel__read(evsel, cpu, thread, count); |
---|
| 1443 | + return perf_evsel__read(&evsel->core, cpu, thread, count); |
---|
1393 | 1444 | } |
---|
1394 | 1445 | |
---|
1395 | 1446 | static void |
---|
1396 | | -perf_evsel__set_count(struct perf_evsel *counter, int cpu, int thread, |
---|
| 1447 | +perf_evsel__set_count(struct evsel *counter, int cpu, int thread, |
---|
1397 | 1448 | u64 val, u64 ena, u64 run) |
---|
1398 | 1449 | { |
---|
1399 | 1450 | struct perf_counts_values *count; |
---|
.. | .. |
---|
1403 | 1454 | count->val = val; |
---|
1404 | 1455 | count->ena = ena; |
---|
1405 | 1456 | count->run = run; |
---|
1406 | | - count->loaded = true; |
---|
| 1457 | + |
---|
| 1458 | + perf_counts__set_loaded(counter->counts, cpu, thread, true); |
---|
1407 | 1459 | } |
---|
1408 | 1460 | |
---|
1409 | 1461 | static int |
---|
1410 | | -perf_evsel__process_group_data(struct perf_evsel *leader, |
---|
| 1462 | +perf_evsel__process_group_data(struct evsel *leader, |
---|
1411 | 1463 | int cpu, int thread, u64 *data) |
---|
1412 | 1464 | { |
---|
1413 | | - u64 read_format = leader->attr.read_format; |
---|
| 1465 | + u64 read_format = leader->core.attr.read_format; |
---|
1414 | 1466 | struct sample_read_value *v; |
---|
1415 | 1467 | u64 nr, ena = 0, run = 0, i; |
---|
1416 | 1468 | |
---|
1417 | 1469 | nr = *data++; |
---|
1418 | 1470 | |
---|
1419 | | - if (nr != (u64) leader->nr_members) |
---|
| 1471 | + if (nr != (u64) leader->core.nr_members) |
---|
1420 | 1472 | return -EINVAL; |
---|
1421 | 1473 | |
---|
1422 | 1474 | if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) |
---|
.. | .. |
---|
1431 | 1483 | v[0].value, ena, run); |
---|
1432 | 1484 | |
---|
1433 | 1485 | for (i = 1; i < nr; i++) { |
---|
1434 | | - struct perf_evsel *counter; |
---|
| 1486 | + struct evsel *counter; |
---|
1435 | 1487 | |
---|
1436 | 1488 | counter = perf_evlist__id2evsel(leader->evlist, v[i].id); |
---|
1437 | 1489 | if (!counter) |
---|
.. | .. |
---|
1444 | 1496 | return 0; |
---|
1445 | 1497 | } |
---|
1446 | 1498 | |
---|
1447 | | -static int |
---|
1448 | | -perf_evsel__read_group(struct perf_evsel *leader, int cpu, int thread) |
---|
| 1499 | +static int evsel__read_group(struct evsel *leader, int cpu, int thread) |
---|
1449 | 1500 | { |
---|
1450 | 1501 | struct perf_stat_evsel *ps = leader->stats; |
---|
1451 | | - u64 read_format = leader->attr.read_format; |
---|
1452 | | - int size = perf_evsel__read_size(leader); |
---|
| 1502 | + u64 read_format = leader->core.attr.read_format; |
---|
| 1503 | + int size = perf_evsel__read_size(&leader->core); |
---|
1453 | 1504 | u64 *data = ps->group_data; |
---|
1454 | 1505 | |
---|
1455 | 1506 | if (!(read_format & PERF_FORMAT_ID)) |
---|
1456 | 1507 | return -EINVAL; |
---|
1457 | 1508 | |
---|
1458 | | - if (!perf_evsel__is_group_leader(leader)) |
---|
| 1509 | + if (!evsel__is_group_leader(leader)) |
---|
1459 | 1510 | return -EINVAL; |
---|
1460 | 1511 | |
---|
1461 | 1512 | if (!data) { |
---|
.. | .. |
---|
1475 | 1526 | return perf_evsel__process_group_data(leader, cpu, thread, data); |
---|
1476 | 1527 | } |
---|
1477 | 1528 | |
---|
1478 | | -int perf_evsel__read_counter(struct perf_evsel *evsel, int cpu, int thread) |
---|
| 1529 | +int evsel__read_counter(struct evsel *evsel, int cpu, int thread) |
---|
1479 | 1530 | { |
---|
1480 | | - u64 read_format = evsel->attr.read_format; |
---|
| 1531 | + u64 read_format = evsel->core.attr.read_format; |
---|
1481 | 1532 | |
---|
1482 | 1533 | if (read_format & PERF_FORMAT_GROUP) |
---|
1483 | | - return perf_evsel__read_group(evsel, cpu, thread); |
---|
1484 | | - else |
---|
1485 | | - return perf_evsel__read_one(evsel, cpu, thread); |
---|
| 1534 | + return evsel__read_group(evsel, cpu, thread); |
---|
| 1535 | + |
---|
| 1536 | + return evsel__read_one(evsel, cpu, thread); |
---|
1486 | 1537 | } |
---|
1487 | 1538 | |
---|
1488 | | -int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, |
---|
1489 | | - int cpu, int thread, bool scale) |
---|
| 1539 | +int __evsel__read_on_cpu(struct evsel *evsel, int cpu, int thread, bool scale) |
---|
1490 | 1540 | { |
---|
1491 | 1541 | struct perf_counts_values count; |
---|
1492 | 1542 | size_t nv = scale ? 3 : 1; |
---|
.. | .. |
---|
1494 | 1544 | if (FD(evsel, cpu, thread) < 0) |
---|
1495 | 1545 | return -EINVAL; |
---|
1496 | 1546 | |
---|
1497 | | - if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1, thread + 1) < 0) |
---|
| 1547 | + if (evsel->counts == NULL && evsel__alloc_counts(evsel, cpu + 1, thread + 1) < 0) |
---|
1498 | 1548 | return -ENOMEM; |
---|
1499 | 1549 | |
---|
1500 | 1550 | if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) <= 0) |
---|
1501 | 1551 | return -errno; |
---|
1502 | 1552 | |
---|
1503 | | - perf_evsel__compute_deltas(evsel, cpu, thread, &count); |
---|
| 1553 | + evsel__compute_deltas(evsel, cpu, thread, &count); |
---|
1504 | 1554 | perf_counts_values__scale(&count, scale, NULL); |
---|
1505 | 1555 | *perf_counts(evsel->counts, cpu, thread) = count; |
---|
1506 | 1556 | return 0; |
---|
1507 | 1557 | } |
---|
1508 | 1558 | |
---|
1509 | | -static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread) |
---|
| 1559 | +static int get_group_fd(struct evsel *evsel, int cpu, int thread) |
---|
1510 | 1560 | { |
---|
1511 | | - struct perf_evsel *leader = evsel->leader; |
---|
| 1561 | + struct evsel *leader = evsel->leader; |
---|
1512 | 1562 | int fd; |
---|
1513 | 1563 | |
---|
1514 | | - if (perf_evsel__is_group_leader(evsel)) |
---|
| 1564 | + if (evsel__is_group_leader(evsel)) |
---|
1515 | 1565 | return -1; |
---|
1516 | 1566 | |
---|
1517 | 1567 | /* |
---|
1518 | 1568 | * Leader must be already processed/open, |
---|
1519 | 1569 | * if not it's a bug. |
---|
1520 | 1570 | */ |
---|
1521 | | - BUG_ON(!leader->fd); |
---|
| 1571 | + BUG_ON(!leader->core.fd); |
---|
1522 | 1572 | |
---|
1523 | 1573 | fd = FD(leader, cpu, thread); |
---|
1524 | 1574 | BUG_ON(fd == -1); |
---|
.. | .. |
---|
1526 | 1576 | return fd; |
---|
1527 | 1577 | } |
---|
1528 | 1578 | |
---|
1529 | | -struct bit_names { |
---|
1530 | | - int bit; |
---|
1531 | | - const char *name; |
---|
1532 | | -}; |
---|
1533 | | - |
---|
1534 | | -static void __p_bits(char *buf, size_t size, u64 value, struct bit_names *bits) |
---|
1535 | | -{ |
---|
1536 | | - bool first_bit = true; |
---|
1537 | | - int i = 0; |
---|
1538 | | - |
---|
1539 | | - do { |
---|
1540 | | - if (value & bits[i].bit) { |
---|
1541 | | - buf += scnprintf(buf, size, "%s%s", first_bit ? "" : "|", bits[i].name); |
---|
1542 | | - first_bit = false; |
---|
1543 | | - } |
---|
1544 | | - } while (bits[++i].name != NULL); |
---|
1545 | | -} |
---|
1546 | | - |
---|
1547 | | -static void __p_sample_type(char *buf, size_t size, u64 value) |
---|
1548 | | -{ |
---|
1549 | | -#define bit_name(n) { PERF_SAMPLE_##n, #n } |
---|
1550 | | - struct bit_names bits[] = { |
---|
1551 | | - bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR), |
---|
1552 | | - bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU), |
---|
1553 | | - bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), |
---|
1554 | | - bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), |
---|
1555 | | - bit_name(IDENTIFIER), bit_name(REGS_INTR), bit_name(DATA_SRC), |
---|
1556 | | - bit_name(WEIGHT), bit_name(PHYS_ADDR), |
---|
1557 | | - { .name = NULL, } |
---|
1558 | | - }; |
---|
1559 | | -#undef bit_name |
---|
1560 | | - __p_bits(buf, size, value, bits); |
---|
1561 | | -} |
---|
1562 | | - |
---|
1563 | | -static void __p_branch_sample_type(char *buf, size_t size, u64 value) |
---|
1564 | | -{ |
---|
1565 | | -#define bit_name(n) { PERF_SAMPLE_BRANCH_##n, #n } |
---|
1566 | | - struct bit_names bits[] = { |
---|
1567 | | - bit_name(USER), bit_name(KERNEL), bit_name(HV), bit_name(ANY), |
---|
1568 | | - bit_name(ANY_CALL), bit_name(ANY_RETURN), bit_name(IND_CALL), |
---|
1569 | | - bit_name(ABORT_TX), bit_name(IN_TX), bit_name(NO_TX), |
---|
1570 | | - bit_name(COND), bit_name(CALL_STACK), bit_name(IND_JUMP), |
---|
1571 | | - bit_name(CALL), bit_name(NO_FLAGS), bit_name(NO_CYCLES), |
---|
1572 | | - { .name = NULL, } |
---|
1573 | | - }; |
---|
1574 | | -#undef bit_name |
---|
1575 | | - __p_bits(buf, size, value, bits); |
---|
1576 | | -} |
---|
1577 | | - |
---|
1578 | | -static void __p_read_format(char *buf, size_t size, u64 value) |
---|
1579 | | -{ |
---|
1580 | | -#define bit_name(n) { PERF_FORMAT_##n, #n } |
---|
1581 | | - struct bit_names bits[] = { |
---|
1582 | | - bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING), |
---|
1583 | | - bit_name(ID), bit_name(GROUP), |
---|
1584 | | - { .name = NULL, } |
---|
1585 | | - }; |
---|
1586 | | -#undef bit_name |
---|
1587 | | - __p_bits(buf, size, value, bits); |
---|
1588 | | -} |
---|
1589 | | - |
---|
1590 | | -#define BUF_SIZE 1024 |
---|
1591 | | - |
---|
1592 | | -#define p_hex(val) snprintf(buf, BUF_SIZE, "%#"PRIx64, (uint64_t)(val)) |
---|
1593 | | -#define p_unsigned(val) snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val)) |
---|
1594 | | -#define p_signed(val) snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val)) |
---|
1595 | | -#define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val) |
---|
1596 | | -#define p_branch_sample_type(val) __p_branch_sample_type(buf, BUF_SIZE, val) |
---|
1597 | | -#define p_read_format(val) __p_read_format(buf, BUF_SIZE, val) |
---|
1598 | | - |
---|
1599 | | -#define PRINT_ATTRn(_n, _f, _p) \ |
---|
1600 | | -do { \ |
---|
1601 | | - if (attr->_f) { \ |
---|
1602 | | - _p(attr->_f); \ |
---|
1603 | | - ret += attr__fprintf(fp, _n, buf, priv);\ |
---|
1604 | | - } \ |
---|
1605 | | -} while (0) |
---|
1606 | | - |
---|
1607 | | -#define PRINT_ATTRf(_f, _p) PRINT_ATTRn(#_f, _f, _p) |
---|
1608 | | - |
---|
1609 | | -int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, |
---|
1610 | | - attr__fprintf_f attr__fprintf, void *priv) |
---|
1611 | | -{ |
---|
1612 | | - char buf[BUF_SIZE]; |
---|
1613 | | - int ret = 0; |
---|
1614 | | - |
---|
1615 | | - PRINT_ATTRf(type, p_unsigned); |
---|
1616 | | - PRINT_ATTRf(size, p_unsigned); |
---|
1617 | | - PRINT_ATTRf(config, p_hex); |
---|
1618 | | - PRINT_ATTRn("{ sample_period, sample_freq }", sample_period, p_unsigned); |
---|
1619 | | - PRINT_ATTRf(sample_type, p_sample_type); |
---|
1620 | | - PRINT_ATTRf(read_format, p_read_format); |
---|
1621 | | - |
---|
1622 | | - PRINT_ATTRf(disabled, p_unsigned); |
---|
1623 | | - PRINT_ATTRf(inherit, p_unsigned); |
---|
1624 | | - PRINT_ATTRf(pinned, p_unsigned); |
---|
1625 | | - PRINT_ATTRf(exclusive, p_unsigned); |
---|
1626 | | - PRINT_ATTRf(exclude_user, p_unsigned); |
---|
1627 | | - PRINT_ATTRf(exclude_kernel, p_unsigned); |
---|
1628 | | - PRINT_ATTRf(exclude_hv, p_unsigned); |
---|
1629 | | - PRINT_ATTRf(exclude_idle, p_unsigned); |
---|
1630 | | - PRINT_ATTRf(mmap, p_unsigned); |
---|
1631 | | - PRINT_ATTRf(comm, p_unsigned); |
---|
1632 | | - PRINT_ATTRf(freq, p_unsigned); |
---|
1633 | | - PRINT_ATTRf(inherit_stat, p_unsigned); |
---|
1634 | | - PRINT_ATTRf(enable_on_exec, p_unsigned); |
---|
1635 | | - PRINT_ATTRf(task, p_unsigned); |
---|
1636 | | - PRINT_ATTRf(watermark, p_unsigned); |
---|
1637 | | - PRINT_ATTRf(precise_ip, p_unsigned); |
---|
1638 | | - PRINT_ATTRf(mmap_data, p_unsigned); |
---|
1639 | | - PRINT_ATTRf(sample_id_all, p_unsigned); |
---|
1640 | | - PRINT_ATTRf(exclude_host, p_unsigned); |
---|
1641 | | - PRINT_ATTRf(exclude_guest, p_unsigned); |
---|
1642 | | - PRINT_ATTRf(exclude_callchain_kernel, p_unsigned); |
---|
1643 | | - PRINT_ATTRf(exclude_callchain_user, p_unsigned); |
---|
1644 | | - PRINT_ATTRf(mmap2, p_unsigned); |
---|
1645 | | - PRINT_ATTRf(comm_exec, p_unsigned); |
---|
1646 | | - PRINT_ATTRf(use_clockid, p_unsigned); |
---|
1647 | | - PRINT_ATTRf(context_switch, p_unsigned); |
---|
1648 | | - PRINT_ATTRf(write_backward, p_unsigned); |
---|
1649 | | - PRINT_ATTRf(namespaces, p_unsigned); |
---|
1650 | | - |
---|
1651 | | - PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned); |
---|
1652 | | - PRINT_ATTRf(bp_type, p_unsigned); |
---|
1653 | | - PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex); |
---|
1654 | | - PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex); |
---|
1655 | | - PRINT_ATTRf(branch_sample_type, p_branch_sample_type); |
---|
1656 | | - PRINT_ATTRf(sample_regs_user, p_hex); |
---|
1657 | | - PRINT_ATTRf(sample_stack_user, p_unsigned); |
---|
1658 | | - PRINT_ATTRf(clockid, p_signed); |
---|
1659 | | - PRINT_ATTRf(sample_regs_intr, p_hex); |
---|
1660 | | - PRINT_ATTRf(aux_watermark, p_unsigned); |
---|
1661 | | - PRINT_ATTRf(sample_max_stack, p_unsigned); |
---|
1662 | | - |
---|
1663 | | - return ret; |
---|
1664 | | -} |
---|
1665 | | - |
---|
1666 | | -static int __open_attr__fprintf(FILE *fp, const char *name, const char *val, |
---|
1667 | | - void *priv __maybe_unused) |
---|
1668 | | -{ |
---|
1669 | | - return fprintf(fp, " %-32s %s\n", name, val); |
---|
1670 | | -} |
---|
1671 | | - |
---|
1672 | | -static void perf_evsel__remove_fd(struct perf_evsel *pos, |
---|
| 1579 | +static void perf_evsel__remove_fd(struct evsel *pos, |
---|
1673 | 1580 | int nr_cpus, int nr_threads, |
---|
1674 | 1581 | int thread_idx) |
---|
1675 | 1582 | { |
---|
.. | .. |
---|
1678 | 1585 | FD(pos, cpu, thread) = FD(pos, cpu, thread + 1); |
---|
1679 | 1586 | } |
---|
1680 | 1587 | |
---|
1681 | | -static int update_fds(struct perf_evsel *evsel, |
---|
| 1588 | +static int update_fds(struct evsel *evsel, |
---|
1682 | 1589 | int nr_cpus, int cpu_idx, |
---|
1683 | 1590 | int nr_threads, int thread_idx) |
---|
1684 | 1591 | { |
---|
1685 | | - struct perf_evsel *pos; |
---|
| 1592 | + struct evsel *pos; |
---|
1686 | 1593 | |
---|
1687 | 1594 | if (cpu_idx >= nr_cpus || thread_idx >= nr_threads) |
---|
1688 | 1595 | return -EINVAL; |
---|
.. | .. |
---|
1702 | 1609 | return 0; |
---|
1703 | 1610 | } |
---|
1704 | 1611 | |
---|
1705 | | -static bool ignore_missing_thread(struct perf_evsel *evsel, |
---|
| 1612 | +static bool ignore_missing_thread(struct evsel *evsel, |
---|
1706 | 1613 | int nr_cpus, int cpu, |
---|
1707 | | - struct thread_map *threads, |
---|
| 1614 | + struct perf_thread_map *threads, |
---|
1708 | 1615 | int thread, int err) |
---|
1709 | 1616 | { |
---|
1710 | | - pid_t ignore_pid = thread_map__pid(threads, thread); |
---|
| 1617 | + pid_t ignore_pid = perf_thread_map__pid(threads, thread); |
---|
1711 | 1618 | |
---|
1712 | 1619 | if (!evsel->ignore_missing_thread) |
---|
1713 | 1620 | return false; |
---|
1714 | 1621 | |
---|
1715 | 1622 | /* The system wide setup does not work with threads. */ |
---|
1716 | | - if (evsel->system_wide) |
---|
| 1623 | + if (evsel->core.system_wide) |
---|
1717 | 1624 | return false; |
---|
1718 | 1625 | |
---|
1719 | 1626 | /* The -ESRCH is perf event syscall errno for pid's not found. */ |
---|
.. | .. |
---|
1739 | 1646 | return true; |
---|
1740 | 1647 | } |
---|
1741 | 1648 | |
---|
1742 | | -int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, |
---|
1743 | | - struct thread_map *threads) |
---|
| 1649 | +static int __open_attr__fprintf(FILE *fp, const char *name, const char *val, |
---|
| 1650 | + void *priv __maybe_unused) |
---|
| 1651 | +{ |
---|
| 1652 | + return fprintf(fp, " %-32s %s\n", name, val); |
---|
| 1653 | +} |
---|
| 1654 | + |
---|
| 1655 | +static void display_attr(struct perf_event_attr *attr) |
---|
| 1656 | +{ |
---|
| 1657 | + if (verbose >= 2 || debug_peo_args) { |
---|
| 1658 | + fprintf(stderr, "%.60s\n", graph_dotted_line); |
---|
| 1659 | + fprintf(stderr, "perf_event_attr:\n"); |
---|
| 1660 | + perf_event_attr__fprintf(stderr, attr, __open_attr__fprintf, NULL); |
---|
| 1661 | + fprintf(stderr, "%.60s\n", graph_dotted_line); |
---|
| 1662 | + } |
---|
| 1663 | +} |
---|
| 1664 | + |
---|
| 1665 | +static int perf_event_open(struct evsel *evsel, |
---|
| 1666 | + pid_t pid, int cpu, int group_fd, |
---|
| 1667 | + unsigned long flags) |
---|
| 1668 | +{ |
---|
| 1669 | + int precise_ip = evsel->core.attr.precise_ip; |
---|
| 1670 | + int fd; |
---|
| 1671 | + |
---|
| 1672 | + while (1) { |
---|
| 1673 | + pr_debug2_peo("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx", |
---|
| 1674 | + pid, cpu, group_fd, flags); |
---|
| 1675 | + |
---|
| 1676 | + fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, group_fd, flags); |
---|
| 1677 | + if (fd >= 0) |
---|
| 1678 | + break; |
---|
| 1679 | + |
---|
| 1680 | + /* Do not try less precise if not requested. */ |
---|
| 1681 | + if (!evsel->precise_max) |
---|
| 1682 | + break; |
---|
| 1683 | + |
---|
| 1684 | + /* |
---|
| 1685 | + * We tried all the precise_ip values, and it's |
---|
| 1686 | + * still failing, so leave it to standard fallback. |
---|
| 1687 | + */ |
---|
| 1688 | + if (!evsel->core.attr.precise_ip) { |
---|
| 1689 | + evsel->core.attr.precise_ip = precise_ip; |
---|
| 1690 | + break; |
---|
| 1691 | + } |
---|
| 1692 | + |
---|
| 1693 | + pr_debug2_peo("\nsys_perf_event_open failed, error %d\n", -ENOTSUP); |
---|
| 1694 | + evsel->core.attr.precise_ip--; |
---|
| 1695 | + pr_debug2_peo("decreasing precise_ip by one (%d)\n", evsel->core.attr.precise_ip); |
---|
| 1696 | + display_attr(&evsel->core.attr); |
---|
| 1697 | + } |
---|
| 1698 | + |
---|
| 1699 | + return fd; |
---|
| 1700 | +} |
---|
| 1701 | + |
---|
| 1702 | +static int evsel__open_cpu(struct evsel *evsel, struct perf_cpu_map *cpus, |
---|
| 1703 | + struct perf_thread_map *threads, |
---|
| 1704 | + int start_cpu, int end_cpu) |
---|
1744 | 1705 | { |
---|
1745 | 1706 | int cpu, thread, nthreads; |
---|
1746 | 1707 | unsigned long flags = PERF_FLAG_FD_CLOEXEC; |
---|
1747 | | - int pid = -1, err; |
---|
| 1708 | + int pid = -1, err, old_errno; |
---|
1748 | 1709 | enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; |
---|
1749 | 1710 | |
---|
1750 | | - if (perf_missing_features.write_backward && evsel->attr.write_backward) |
---|
| 1711 | + if ((perf_missing_features.write_backward && evsel->core.attr.write_backward) || |
---|
| 1712 | + (perf_missing_features.aux_output && evsel->core.attr.aux_output)) |
---|
1751 | 1713 | return -EINVAL; |
---|
1752 | 1714 | |
---|
1753 | 1715 | if (cpus == NULL) { |
---|
1754 | | - static struct cpu_map *empty_cpu_map; |
---|
| 1716 | + static struct perf_cpu_map *empty_cpu_map; |
---|
1755 | 1717 | |
---|
1756 | 1718 | if (empty_cpu_map == NULL) { |
---|
1757 | | - empty_cpu_map = cpu_map__dummy_new(); |
---|
| 1719 | + empty_cpu_map = perf_cpu_map__dummy_new(); |
---|
1758 | 1720 | if (empty_cpu_map == NULL) |
---|
1759 | 1721 | return -ENOMEM; |
---|
1760 | 1722 | } |
---|
.. | .. |
---|
1763 | 1725 | } |
---|
1764 | 1726 | |
---|
1765 | 1727 | if (threads == NULL) { |
---|
1766 | | - static struct thread_map *empty_thread_map; |
---|
| 1728 | + static struct perf_thread_map *empty_thread_map; |
---|
1767 | 1729 | |
---|
1768 | 1730 | if (empty_thread_map == NULL) { |
---|
1769 | 1731 | empty_thread_map = thread_map__new_by_tid(-1); |
---|
.. | .. |
---|
1774 | 1736 | threads = empty_thread_map; |
---|
1775 | 1737 | } |
---|
1776 | 1738 | |
---|
1777 | | - if (evsel->system_wide) |
---|
| 1739 | + if (evsel->core.system_wide) |
---|
1778 | 1740 | nthreads = 1; |
---|
1779 | 1741 | else |
---|
1780 | 1742 | nthreads = threads->nr; |
---|
1781 | 1743 | |
---|
1782 | | - if (evsel->fd == NULL && |
---|
1783 | | - perf_evsel__alloc_fd(evsel, cpus->nr, nthreads) < 0) |
---|
| 1744 | + if (evsel->core.fd == NULL && |
---|
| 1745 | + perf_evsel__alloc_fd(&evsel->core, cpus->nr, nthreads) < 0) |
---|
1784 | 1746 | return -ENOMEM; |
---|
1785 | 1747 | |
---|
1786 | 1748 | if (evsel->cgrp) { |
---|
.. | .. |
---|
1790 | 1752 | |
---|
1791 | 1753 | fallback_missing_features: |
---|
1792 | 1754 | if (perf_missing_features.clockid_wrong) |
---|
1793 | | - evsel->attr.clockid = CLOCK_MONOTONIC; /* should always work */ |
---|
| 1755 | + evsel->core.attr.clockid = CLOCK_MONOTONIC; /* should always work */ |
---|
1794 | 1756 | if (perf_missing_features.clockid) { |
---|
1795 | | - evsel->attr.use_clockid = 0; |
---|
1796 | | - evsel->attr.clockid = 0; |
---|
| 1757 | + evsel->core.attr.use_clockid = 0; |
---|
| 1758 | + evsel->core.attr.clockid = 0; |
---|
1797 | 1759 | } |
---|
1798 | 1760 | if (perf_missing_features.cloexec) |
---|
1799 | 1761 | flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC; |
---|
1800 | 1762 | if (perf_missing_features.mmap2) |
---|
1801 | | - evsel->attr.mmap2 = 0; |
---|
| 1763 | + evsel->core.attr.mmap2 = 0; |
---|
1802 | 1764 | if (perf_missing_features.exclude_guest) |
---|
1803 | | - evsel->attr.exclude_guest = evsel->attr.exclude_host = 0; |
---|
| 1765 | + evsel->core.attr.exclude_guest = evsel->core.attr.exclude_host = 0; |
---|
1804 | 1766 | if (perf_missing_features.lbr_flags) |
---|
1805 | | - evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | |
---|
| 1767 | + evsel->core.attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | |
---|
1806 | 1768 | PERF_SAMPLE_BRANCH_NO_CYCLES); |
---|
1807 | | - if (perf_missing_features.group_read && evsel->attr.inherit) |
---|
1808 | | - evsel->attr.read_format &= ~(PERF_FORMAT_GROUP|PERF_FORMAT_ID); |
---|
| 1769 | + if (perf_missing_features.group_read && evsel->core.attr.inherit) |
---|
| 1770 | + evsel->core.attr.read_format &= ~(PERF_FORMAT_GROUP|PERF_FORMAT_ID); |
---|
| 1771 | + if (perf_missing_features.ksymbol) |
---|
| 1772 | + evsel->core.attr.ksymbol = 0; |
---|
| 1773 | + if (perf_missing_features.bpf) |
---|
| 1774 | + evsel->core.attr.bpf_event = 0; |
---|
| 1775 | + if (perf_missing_features.branch_hw_idx) |
---|
| 1776 | + evsel->core.attr.branch_sample_type &= ~PERF_SAMPLE_BRANCH_HW_INDEX; |
---|
1809 | 1777 | retry_sample_id: |
---|
1810 | 1778 | if (perf_missing_features.sample_id_all) |
---|
1811 | | - evsel->attr.sample_id_all = 0; |
---|
| 1779 | + evsel->core.attr.sample_id_all = 0; |
---|
1812 | 1780 | |
---|
1813 | | - if (verbose >= 2) { |
---|
1814 | | - fprintf(stderr, "%.60s\n", graph_dotted_line); |
---|
1815 | | - fprintf(stderr, "perf_event_attr:\n"); |
---|
1816 | | - perf_event_attr__fprintf(stderr, &evsel->attr, __open_attr__fprintf, NULL); |
---|
1817 | | - fprintf(stderr, "%.60s\n", graph_dotted_line); |
---|
1818 | | - } |
---|
| 1781 | + display_attr(&evsel->core.attr); |
---|
1819 | 1782 | |
---|
1820 | | - for (cpu = 0; cpu < cpus->nr; cpu++) { |
---|
| 1783 | + for (cpu = start_cpu; cpu < end_cpu; cpu++) { |
---|
1821 | 1784 | |
---|
1822 | 1785 | for (thread = 0; thread < nthreads; thread++) { |
---|
1823 | 1786 | int fd, group_fd; |
---|
1824 | 1787 | |
---|
1825 | | - if (!evsel->cgrp && !evsel->system_wide) |
---|
1826 | | - pid = thread_map__pid(threads, thread); |
---|
| 1788 | + if (!evsel->cgrp && !evsel->core.system_wide) |
---|
| 1789 | + pid = perf_thread_map__pid(threads, thread); |
---|
1827 | 1790 | |
---|
1828 | 1791 | group_fd = get_group_fd(evsel, cpu, thread); |
---|
1829 | 1792 | retry_open: |
---|
1830 | | - pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx", |
---|
1831 | | - pid, cpus->map[cpu], group_fd, flags); |
---|
1832 | | - |
---|
1833 | 1793 | test_attr__ready(); |
---|
1834 | 1794 | |
---|
1835 | | - fd = sys_perf_event_open(&evsel->attr, pid, cpus->map[cpu], |
---|
1836 | | - group_fd, flags); |
---|
| 1795 | + fd = perf_event_open(evsel, pid, cpus->map[cpu], |
---|
| 1796 | + group_fd, flags); |
---|
1837 | 1797 | |
---|
1838 | 1798 | FD(evsel, cpu, thread) = fd; |
---|
| 1799 | + |
---|
| 1800 | + if (unlikely(test_attr__enabled)) { |
---|
| 1801 | + test_attr__open(&evsel->core.attr, pid, cpus->map[cpu], |
---|
| 1802 | + fd, group_fd, flags); |
---|
| 1803 | + } |
---|
1839 | 1804 | |
---|
1840 | 1805 | if (fd < 0) { |
---|
1841 | 1806 | err = -errno; |
---|
.. | .. |
---|
1854 | 1819 | continue; |
---|
1855 | 1820 | } |
---|
1856 | 1821 | |
---|
1857 | | - pr_debug2("\nsys_perf_event_open failed, error %d\n", |
---|
| 1822 | + pr_debug2_peo("\nsys_perf_event_open failed, error %d\n", |
---|
1858 | 1823 | err); |
---|
1859 | 1824 | goto try_fallback; |
---|
1860 | 1825 | } |
---|
1861 | 1826 | |
---|
1862 | | - pr_debug2(" = %d\n", fd); |
---|
| 1827 | + pr_debug2_peo(" = %d\n", fd); |
---|
1863 | 1828 | |
---|
1864 | 1829 | if (evsel->bpf_fd >= 0) { |
---|
1865 | 1830 | int evt_fd = fd; |
---|
.. | .. |
---|
1880 | 1845 | |
---|
1881 | 1846 | /* |
---|
1882 | 1847 | * If we succeeded but had to kill clockid, fail and |
---|
1883 | | - * have perf_evsel__open_strerror() print us a nice |
---|
1884 | | - * error. |
---|
| 1848 | + * have evsel__open_strerror() print us a nice error. |
---|
1885 | 1849 | */ |
---|
1886 | 1850 | if (perf_missing_features.clockid || |
---|
1887 | 1851 | perf_missing_features.clockid_wrong) { |
---|
.. | .. |
---|
1900 | 1864 | */ |
---|
1901 | 1865 | if (err == -EMFILE && set_rlimit < INCREASED_MAX) { |
---|
1902 | 1866 | struct rlimit l; |
---|
1903 | | - int old_errno = errno; |
---|
1904 | 1867 | |
---|
| 1868 | + old_errno = errno; |
---|
1905 | 1869 | if (getrlimit(RLIMIT_NOFILE, &l) == 0) { |
---|
1906 | 1870 | if (set_rlimit == NO_CHANGE) |
---|
1907 | 1871 | l.rlim_cur = l.rlim_max; |
---|
.. | .. |
---|
1925 | 1889 | * Must probe features in the order they were added to the |
---|
1926 | 1890 | * perf_event_attr interface. |
---|
1927 | 1891 | */ |
---|
1928 | | - if (!perf_missing_features.write_backward && evsel->attr.write_backward) { |
---|
1929 | | - perf_missing_features.write_backward = true; |
---|
1930 | | - pr_debug2("switching off write_backward\n"); |
---|
| 1892 | + if (!perf_missing_features.cgroup && evsel->core.attr.cgroup) { |
---|
| 1893 | + perf_missing_features.cgroup = true; |
---|
| 1894 | + pr_debug2_peo("Kernel has no cgroup sampling support, bailing out\n"); |
---|
1931 | 1895 | goto out_close; |
---|
1932 | | - } else if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) { |
---|
1933 | | - perf_missing_features.clockid_wrong = true; |
---|
1934 | | - pr_debug2("switching off clockid\n"); |
---|
| 1896 | + } else if (!perf_missing_features.branch_hw_idx && |
---|
| 1897 | + (evsel->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_HW_INDEX)) { |
---|
| 1898 | + perf_missing_features.branch_hw_idx = true; |
---|
| 1899 | + pr_debug2("switching off branch HW index support\n"); |
---|
1935 | 1900 | goto fallback_missing_features; |
---|
1936 | | - } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) { |
---|
| 1901 | + } else if (!perf_missing_features.aux_output && evsel->core.attr.aux_output) { |
---|
| 1902 | + perf_missing_features.aux_output = true; |
---|
| 1903 | + pr_debug2_peo("Kernel has no attr.aux_output support, bailing out\n"); |
---|
| 1904 | + goto out_close; |
---|
| 1905 | + } else if (!perf_missing_features.bpf && evsel->core.attr.bpf_event) { |
---|
| 1906 | + perf_missing_features.bpf = true; |
---|
| 1907 | + pr_debug2_peo("switching off bpf_event\n"); |
---|
| 1908 | + goto fallback_missing_features; |
---|
| 1909 | + } else if (!perf_missing_features.ksymbol && evsel->core.attr.ksymbol) { |
---|
| 1910 | + perf_missing_features.ksymbol = true; |
---|
| 1911 | + pr_debug2_peo("switching off ksymbol\n"); |
---|
| 1912 | + goto fallback_missing_features; |
---|
| 1913 | + } else if (!perf_missing_features.write_backward && evsel->core.attr.write_backward) { |
---|
| 1914 | + perf_missing_features.write_backward = true; |
---|
| 1915 | + pr_debug2_peo("switching off write_backward\n"); |
---|
| 1916 | + goto out_close; |
---|
| 1917 | + } else if (!perf_missing_features.clockid_wrong && evsel->core.attr.use_clockid) { |
---|
| 1918 | + perf_missing_features.clockid_wrong = true; |
---|
| 1919 | + pr_debug2_peo("switching off clockid\n"); |
---|
| 1920 | + goto fallback_missing_features; |
---|
| 1921 | + } else if (!perf_missing_features.clockid && evsel->core.attr.use_clockid) { |
---|
1937 | 1922 | perf_missing_features.clockid = true; |
---|
1938 | | - pr_debug2("switching off use_clockid\n"); |
---|
| 1923 | + pr_debug2_peo("switching off use_clockid\n"); |
---|
1939 | 1924 | goto fallback_missing_features; |
---|
1940 | 1925 | } else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) { |
---|
1941 | 1926 | perf_missing_features.cloexec = true; |
---|
1942 | | - pr_debug2("switching off cloexec flag\n"); |
---|
| 1927 | + pr_debug2_peo("switching off cloexec flag\n"); |
---|
1943 | 1928 | goto fallback_missing_features; |
---|
1944 | | - } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) { |
---|
| 1929 | + } else if (!perf_missing_features.mmap2 && evsel->core.attr.mmap2) { |
---|
1945 | 1930 | perf_missing_features.mmap2 = true; |
---|
1946 | | - pr_debug2("switching off mmap2\n"); |
---|
| 1931 | + pr_debug2_peo("switching off mmap2\n"); |
---|
1947 | 1932 | goto fallback_missing_features; |
---|
1948 | 1933 | } else if (!perf_missing_features.exclude_guest && |
---|
1949 | | - (evsel->attr.exclude_guest || evsel->attr.exclude_host)) { |
---|
| 1934 | + (evsel->core.attr.exclude_guest || evsel->core.attr.exclude_host)) { |
---|
1950 | 1935 | perf_missing_features.exclude_guest = true; |
---|
1951 | | - pr_debug2("switching off exclude_guest, exclude_host\n"); |
---|
| 1936 | + pr_debug2_peo("switching off exclude_guest, exclude_host\n"); |
---|
1952 | 1937 | goto fallback_missing_features; |
---|
1953 | 1938 | } else if (!perf_missing_features.sample_id_all) { |
---|
1954 | 1939 | perf_missing_features.sample_id_all = true; |
---|
1955 | | - pr_debug2("switching off sample_id_all\n"); |
---|
| 1940 | + pr_debug2_peo("switching off sample_id_all\n"); |
---|
1956 | 1941 | goto retry_sample_id; |
---|
1957 | 1942 | } else if (!perf_missing_features.lbr_flags && |
---|
1958 | | - (evsel->attr.branch_sample_type & |
---|
| 1943 | + (evsel->core.attr.branch_sample_type & |
---|
1959 | 1944 | (PERF_SAMPLE_BRANCH_NO_CYCLES | |
---|
1960 | 1945 | PERF_SAMPLE_BRANCH_NO_FLAGS))) { |
---|
1961 | 1946 | perf_missing_features.lbr_flags = true; |
---|
1962 | | - pr_debug2("switching off branch sample type no (cycles/flags)\n"); |
---|
| 1947 | + pr_debug2_peo("switching off branch sample type no (cycles/flags)\n"); |
---|
1963 | 1948 | goto fallback_missing_features; |
---|
1964 | 1949 | } else if (!perf_missing_features.group_read && |
---|
1965 | | - evsel->attr.inherit && |
---|
1966 | | - (evsel->attr.read_format & PERF_FORMAT_GROUP) && |
---|
1967 | | - perf_evsel__is_group_leader(evsel)) { |
---|
| 1950 | + evsel->core.attr.inherit && |
---|
| 1951 | + (evsel->core.attr.read_format & PERF_FORMAT_GROUP) && |
---|
| 1952 | + evsel__is_group_leader(evsel)) { |
---|
1968 | 1953 | perf_missing_features.group_read = true; |
---|
1969 | | - pr_debug2("switching off group read\n"); |
---|
| 1954 | + pr_debug2_peo("switching off group read\n"); |
---|
1970 | 1955 | goto fallback_missing_features; |
---|
1971 | 1956 | } |
---|
1972 | 1957 | out_close: |
---|
1973 | 1958 | if (err) |
---|
1974 | 1959 | threads->err_thread = thread; |
---|
1975 | 1960 | |
---|
| 1961 | + old_errno = errno; |
---|
1976 | 1962 | do { |
---|
1977 | 1963 | while (--thread >= 0) { |
---|
1978 | | - close(FD(evsel, cpu, thread)); |
---|
| 1964 | + if (FD(evsel, cpu, thread) >= 0) |
---|
| 1965 | + close(FD(evsel, cpu, thread)); |
---|
1979 | 1966 | FD(evsel, cpu, thread) = -1; |
---|
1980 | 1967 | } |
---|
1981 | 1968 | thread = nthreads; |
---|
1982 | 1969 | } while (--cpu >= 0); |
---|
| 1970 | + errno = old_errno; |
---|
1983 | 1971 | return err; |
---|
1984 | 1972 | } |
---|
1985 | 1973 | |
---|
1986 | | -void perf_evsel__close(struct perf_evsel *evsel) |
---|
| 1974 | +int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus, |
---|
| 1975 | + struct perf_thread_map *threads) |
---|
1987 | 1976 | { |
---|
1988 | | - if (evsel->fd == NULL) |
---|
1989 | | - return; |
---|
1990 | | - |
---|
1991 | | - perf_evsel__close_fd(evsel); |
---|
1992 | | - perf_evsel__free_fd(evsel); |
---|
| 1977 | + return evsel__open_cpu(evsel, cpus, threads, 0, cpus ? cpus->nr : 1); |
---|
1993 | 1978 | } |
---|
1994 | 1979 | |
---|
1995 | | -int perf_evsel__open_per_cpu(struct perf_evsel *evsel, |
---|
1996 | | - struct cpu_map *cpus) |
---|
| 1980 | +void evsel__close(struct evsel *evsel) |
---|
1997 | 1981 | { |
---|
1998 | | - return perf_evsel__open(evsel, cpus, NULL); |
---|
| 1982 | + perf_evsel__close(&evsel->core); |
---|
| 1983 | + perf_evsel__free_id(&evsel->core); |
---|
1999 | 1984 | } |
---|
2000 | 1985 | |
---|
2001 | | -int perf_evsel__open_per_thread(struct perf_evsel *evsel, |
---|
2002 | | - struct thread_map *threads) |
---|
| 1986 | +int evsel__open_per_cpu(struct evsel *evsel, struct perf_cpu_map *cpus, int cpu) |
---|
2003 | 1987 | { |
---|
2004 | | - return perf_evsel__open(evsel, NULL, threads); |
---|
| 1988 | + if (cpu == -1) |
---|
| 1989 | + return evsel__open_cpu(evsel, cpus, NULL, 0, |
---|
| 1990 | + cpus ? cpus->nr : 1); |
---|
| 1991 | + |
---|
| 1992 | + return evsel__open_cpu(evsel, cpus, NULL, cpu, cpu + 1); |
---|
2005 | 1993 | } |
---|
2006 | 1994 | |
---|
2007 | | -static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel, |
---|
| 1995 | +int evsel__open_per_thread(struct evsel *evsel, struct perf_thread_map *threads) |
---|
| 1996 | +{ |
---|
| 1997 | + return evsel__open(evsel, NULL, threads); |
---|
| 1998 | +} |
---|
| 1999 | + |
---|
| 2000 | +static int perf_evsel__parse_id_sample(const struct evsel *evsel, |
---|
2008 | 2001 | const union perf_event *event, |
---|
2009 | 2002 | struct perf_sample *sample) |
---|
2010 | 2003 | { |
---|
2011 | | - u64 type = evsel->attr.sample_type; |
---|
2012 | | - const u64 *array = event->sample.array; |
---|
| 2004 | + u64 type = evsel->core.attr.sample_type; |
---|
| 2005 | + const __u64 *array = event->sample.array; |
---|
2013 | 2006 | bool swapped = evsel->needs_swap; |
---|
2014 | 2007 | union u64_swap u; |
---|
2015 | 2008 | |
---|
.. | .. |
---|
2094 | 2087 | return 0; |
---|
2095 | 2088 | } |
---|
2096 | 2089 | |
---|
2097 | | -int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, |
---|
2098 | | - struct perf_sample *data) |
---|
| 2090 | +int evsel__parse_sample(struct evsel *evsel, union perf_event *event, |
---|
| 2091 | + struct perf_sample *data) |
---|
2099 | 2092 | { |
---|
2100 | | - u64 type = evsel->attr.sample_type; |
---|
| 2093 | + u64 type = evsel->core.attr.sample_type; |
---|
2101 | 2094 | bool swapped = evsel->needs_swap; |
---|
2102 | | - const u64 *array; |
---|
| 2095 | + const __u64 *array; |
---|
2103 | 2096 | u16 max_size = event->header.size; |
---|
2104 | 2097 | const void *endp = (void *)event + max_size; |
---|
2105 | 2098 | u64 sz; |
---|
.. | .. |
---|
2113 | 2106 | memset(data, 0, sizeof(*data)); |
---|
2114 | 2107 | data->cpu = data->pid = data->tid = -1; |
---|
2115 | 2108 | data->stream_id = data->id = data->time = -1ULL; |
---|
2116 | | - data->period = evsel->attr.sample_period; |
---|
| 2109 | + data->period = evsel->core.attr.sample_period; |
---|
2117 | 2110 | data->cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
---|
2118 | 2111 | data->misc = event->header.misc; |
---|
2119 | 2112 | data->id = -1ULL; |
---|
2120 | 2113 | data->data_src = PERF_MEM_DATA_SRC_NONE; |
---|
2121 | 2114 | |
---|
2122 | 2115 | if (event->header.type != PERF_RECORD_SAMPLE) { |
---|
2123 | | - if (!evsel->attr.sample_id_all) |
---|
| 2116 | + if (!evsel->core.attr.sample_id_all) |
---|
2124 | 2117 | return 0; |
---|
2125 | 2118 | return perf_evsel__parse_id_sample(evsel, event, data); |
---|
2126 | 2119 | } |
---|
.. | .. |
---|
2193 | 2186 | } |
---|
2194 | 2187 | |
---|
2195 | 2188 | if (type & PERF_SAMPLE_READ) { |
---|
2196 | | - u64 read_format = evsel->attr.read_format; |
---|
| 2189 | + u64 read_format = evsel->core.attr.read_format; |
---|
2197 | 2190 | |
---|
2198 | 2191 | OVERFLOW_CHECK_u64(array); |
---|
2199 | 2192 | if (read_format & PERF_FORMAT_GROUP) |
---|
.. | .. |
---|
2235 | 2228 | } |
---|
2236 | 2229 | } |
---|
2237 | 2230 | |
---|
2238 | | - if (evsel__has_callchain(evsel)) { |
---|
| 2231 | + if (type & PERF_SAMPLE_CALLCHAIN) { |
---|
2239 | 2232 | const u64 max_callchain_nr = UINT64_MAX / sizeof(u64); |
---|
2240 | 2233 | |
---|
2241 | 2234 | OVERFLOW_CHECK_u64(array); |
---|
.. | .. |
---|
2287 | 2280 | |
---|
2288 | 2281 | if (data->branch_stack->nr > max_branch_nr) |
---|
2289 | 2282 | return -EFAULT; |
---|
| 2283 | + |
---|
2290 | 2284 | sz = data->branch_stack->nr * sizeof(struct branch_entry); |
---|
| 2285 | + if (evsel__has_branch_hw_idx(evsel)) |
---|
| 2286 | + sz += sizeof(u64); |
---|
| 2287 | + else |
---|
| 2288 | + data->no_hw_idx = true; |
---|
2291 | 2289 | OVERFLOW_CHECK(array, sz, max_size); |
---|
2292 | 2290 | array = (void *)array + sz; |
---|
2293 | 2291 | } |
---|
.. | .. |
---|
2298 | 2296 | array++; |
---|
2299 | 2297 | |
---|
2300 | 2298 | if (data->user_regs.abi) { |
---|
2301 | | - u64 mask = evsel->attr.sample_regs_user; |
---|
| 2299 | + u64 mask = evsel->core.attr.sample_regs_user; |
---|
2302 | 2300 | |
---|
2303 | | - sz = hweight_long(mask) * sizeof(u64); |
---|
| 2301 | + sz = hweight64(mask) * sizeof(u64); |
---|
2304 | 2302 | OVERFLOW_CHECK(array, sz, max_size); |
---|
2305 | 2303 | data->user_regs.mask = mask; |
---|
2306 | 2304 | data->user_regs.regs = (u64 *)array; |
---|
.. | .. |
---|
2354 | 2352 | array++; |
---|
2355 | 2353 | |
---|
2356 | 2354 | if (data->intr_regs.abi != PERF_SAMPLE_REGS_ABI_NONE) { |
---|
2357 | | - u64 mask = evsel->attr.sample_regs_intr; |
---|
| 2355 | + u64 mask = evsel->core.attr.sample_regs_intr; |
---|
2358 | 2356 | |
---|
2359 | | - sz = hweight_long(mask) * sizeof(u64); |
---|
| 2357 | + sz = hweight64(mask) * sizeof(u64); |
---|
2360 | 2358 | OVERFLOW_CHECK(array, sz, max_size); |
---|
2361 | 2359 | data->intr_regs.mask = mask; |
---|
2362 | 2360 | data->intr_regs.regs = (u64 *)array; |
---|
.. | .. |
---|
2370 | 2368 | array++; |
---|
2371 | 2369 | } |
---|
2372 | 2370 | |
---|
| 2371 | + data->cgroup = 0; |
---|
| 2372 | + if (type & PERF_SAMPLE_CGROUP) { |
---|
| 2373 | + data->cgroup = *array; |
---|
| 2374 | + array++; |
---|
| 2375 | + } |
---|
| 2376 | + |
---|
| 2377 | + if (type & PERF_SAMPLE_AUX) { |
---|
| 2378 | + OVERFLOW_CHECK_u64(array); |
---|
| 2379 | + sz = *array++; |
---|
| 2380 | + |
---|
| 2381 | + OVERFLOW_CHECK(array, sz, max_size); |
---|
| 2382 | + /* Undo swap of data */ |
---|
| 2383 | + if (swapped) |
---|
| 2384 | + mem_bswap_64((char *)array, sz); |
---|
| 2385 | + data->aux_sample.size = sz; |
---|
| 2386 | + data->aux_sample.data = (char *)array; |
---|
| 2387 | + array = (void *)array + sz; |
---|
| 2388 | + } |
---|
| 2389 | + |
---|
2373 | 2390 | return 0; |
---|
2374 | 2391 | } |
---|
2375 | 2392 | |
---|
2376 | | -int perf_evsel__parse_sample_timestamp(struct perf_evsel *evsel, |
---|
2377 | | - union perf_event *event, |
---|
2378 | | - u64 *timestamp) |
---|
| 2393 | +int evsel__parse_sample_timestamp(struct evsel *evsel, union perf_event *event, |
---|
| 2394 | + u64 *timestamp) |
---|
2379 | 2395 | { |
---|
2380 | | - u64 type = evsel->attr.sample_type; |
---|
2381 | | - const u64 *array; |
---|
| 2396 | + u64 type = evsel->core.attr.sample_type; |
---|
| 2397 | + const __u64 *array; |
---|
2382 | 2398 | |
---|
2383 | 2399 | if (!(type & PERF_SAMPLE_TIME)) |
---|
2384 | 2400 | return -1; |
---|
.. | .. |
---|
2388 | 2404 | .time = -1ULL, |
---|
2389 | 2405 | }; |
---|
2390 | 2406 | |
---|
2391 | | - if (!evsel->attr.sample_id_all) |
---|
| 2407 | + if (!evsel->core.attr.sample_id_all) |
---|
2392 | 2408 | return -1; |
---|
2393 | 2409 | if (perf_evsel__parse_id_sample(evsel, event, &data)) |
---|
2394 | 2410 | return -1; |
---|
.. | .. |
---|
2417 | 2433 | return 0; |
---|
2418 | 2434 | } |
---|
2419 | 2435 | |
---|
2420 | | -size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, |
---|
2421 | | - u64 read_format) |
---|
2422 | | -{ |
---|
2423 | | - size_t sz, result = sizeof(struct sample_event); |
---|
2424 | | - |
---|
2425 | | - if (type & PERF_SAMPLE_IDENTIFIER) |
---|
2426 | | - result += sizeof(u64); |
---|
2427 | | - |
---|
2428 | | - if (type & PERF_SAMPLE_IP) |
---|
2429 | | - result += sizeof(u64); |
---|
2430 | | - |
---|
2431 | | - if (type & PERF_SAMPLE_TID) |
---|
2432 | | - result += sizeof(u64); |
---|
2433 | | - |
---|
2434 | | - if (type & PERF_SAMPLE_TIME) |
---|
2435 | | - result += sizeof(u64); |
---|
2436 | | - |
---|
2437 | | - if (type & PERF_SAMPLE_ADDR) |
---|
2438 | | - result += sizeof(u64); |
---|
2439 | | - |
---|
2440 | | - if (type & PERF_SAMPLE_ID) |
---|
2441 | | - result += sizeof(u64); |
---|
2442 | | - |
---|
2443 | | - if (type & PERF_SAMPLE_STREAM_ID) |
---|
2444 | | - result += sizeof(u64); |
---|
2445 | | - |
---|
2446 | | - if (type & PERF_SAMPLE_CPU) |
---|
2447 | | - result += sizeof(u64); |
---|
2448 | | - |
---|
2449 | | - if (type & PERF_SAMPLE_PERIOD) |
---|
2450 | | - result += sizeof(u64); |
---|
2451 | | - |
---|
2452 | | - if (type & PERF_SAMPLE_READ) { |
---|
2453 | | - result += sizeof(u64); |
---|
2454 | | - if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) |
---|
2455 | | - result += sizeof(u64); |
---|
2456 | | - if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) |
---|
2457 | | - result += sizeof(u64); |
---|
2458 | | - /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */ |
---|
2459 | | - if (read_format & PERF_FORMAT_GROUP) { |
---|
2460 | | - sz = sample->read.group.nr * |
---|
2461 | | - sizeof(struct sample_read_value); |
---|
2462 | | - result += sz; |
---|
2463 | | - } else { |
---|
2464 | | - result += sizeof(u64); |
---|
2465 | | - } |
---|
2466 | | - } |
---|
2467 | | - |
---|
2468 | | - if (type & PERF_SAMPLE_CALLCHAIN) { |
---|
2469 | | - sz = (sample->callchain->nr + 1) * sizeof(u64); |
---|
2470 | | - result += sz; |
---|
2471 | | - } |
---|
2472 | | - |
---|
2473 | | - if (type & PERF_SAMPLE_RAW) { |
---|
2474 | | - result += sizeof(u32); |
---|
2475 | | - result += sample->raw_size; |
---|
2476 | | - } |
---|
2477 | | - |
---|
2478 | | - if (type & PERF_SAMPLE_BRANCH_STACK) { |
---|
2479 | | - sz = sample->branch_stack->nr * sizeof(struct branch_entry); |
---|
2480 | | - sz += sizeof(u64); |
---|
2481 | | - result += sz; |
---|
2482 | | - } |
---|
2483 | | - |
---|
2484 | | - if (type & PERF_SAMPLE_REGS_USER) { |
---|
2485 | | - if (sample->user_regs.abi) { |
---|
2486 | | - result += sizeof(u64); |
---|
2487 | | - sz = hweight_long(sample->user_regs.mask) * sizeof(u64); |
---|
2488 | | - result += sz; |
---|
2489 | | - } else { |
---|
2490 | | - result += sizeof(u64); |
---|
2491 | | - } |
---|
2492 | | - } |
---|
2493 | | - |
---|
2494 | | - if (type & PERF_SAMPLE_STACK_USER) { |
---|
2495 | | - sz = sample->user_stack.size; |
---|
2496 | | - result += sizeof(u64); |
---|
2497 | | - if (sz) { |
---|
2498 | | - result += sz; |
---|
2499 | | - result += sizeof(u64); |
---|
2500 | | - } |
---|
2501 | | - } |
---|
2502 | | - |
---|
2503 | | - if (type & PERF_SAMPLE_WEIGHT) |
---|
2504 | | - result += sizeof(u64); |
---|
2505 | | - |
---|
2506 | | - if (type & PERF_SAMPLE_DATA_SRC) |
---|
2507 | | - result += sizeof(u64); |
---|
2508 | | - |
---|
2509 | | - if (type & PERF_SAMPLE_TRANSACTION) |
---|
2510 | | - result += sizeof(u64); |
---|
2511 | | - |
---|
2512 | | - if (type & PERF_SAMPLE_REGS_INTR) { |
---|
2513 | | - if (sample->intr_regs.abi) { |
---|
2514 | | - result += sizeof(u64); |
---|
2515 | | - sz = hweight_long(sample->intr_regs.mask) * sizeof(u64); |
---|
2516 | | - result += sz; |
---|
2517 | | - } else { |
---|
2518 | | - result += sizeof(u64); |
---|
2519 | | - } |
---|
2520 | | - } |
---|
2521 | | - |
---|
2522 | | - if (type & PERF_SAMPLE_PHYS_ADDR) |
---|
2523 | | - result += sizeof(u64); |
---|
2524 | | - |
---|
2525 | | - return result; |
---|
2526 | | -} |
---|
2527 | | - |
---|
2528 | | -int perf_event__synthesize_sample(union perf_event *event, u64 type, |
---|
2529 | | - u64 read_format, |
---|
2530 | | - const struct perf_sample *sample) |
---|
2531 | | -{ |
---|
2532 | | - u64 *array; |
---|
2533 | | - size_t sz; |
---|
2534 | | - /* |
---|
2535 | | - * used for cross-endian analysis. See git commit 65014ab3 |
---|
2536 | | - * for why this goofiness is needed. |
---|
2537 | | - */ |
---|
2538 | | - union u64_swap u; |
---|
2539 | | - |
---|
2540 | | - array = event->sample.array; |
---|
2541 | | - |
---|
2542 | | - if (type & PERF_SAMPLE_IDENTIFIER) { |
---|
2543 | | - *array = sample->id; |
---|
2544 | | - array++; |
---|
2545 | | - } |
---|
2546 | | - |
---|
2547 | | - if (type & PERF_SAMPLE_IP) { |
---|
2548 | | - *array = sample->ip; |
---|
2549 | | - array++; |
---|
2550 | | - } |
---|
2551 | | - |
---|
2552 | | - if (type & PERF_SAMPLE_TID) { |
---|
2553 | | - u.val32[0] = sample->pid; |
---|
2554 | | - u.val32[1] = sample->tid; |
---|
2555 | | - *array = u.val64; |
---|
2556 | | - array++; |
---|
2557 | | - } |
---|
2558 | | - |
---|
2559 | | - if (type & PERF_SAMPLE_TIME) { |
---|
2560 | | - *array = sample->time; |
---|
2561 | | - array++; |
---|
2562 | | - } |
---|
2563 | | - |
---|
2564 | | - if (type & PERF_SAMPLE_ADDR) { |
---|
2565 | | - *array = sample->addr; |
---|
2566 | | - array++; |
---|
2567 | | - } |
---|
2568 | | - |
---|
2569 | | - if (type & PERF_SAMPLE_ID) { |
---|
2570 | | - *array = sample->id; |
---|
2571 | | - array++; |
---|
2572 | | - } |
---|
2573 | | - |
---|
2574 | | - if (type & PERF_SAMPLE_STREAM_ID) { |
---|
2575 | | - *array = sample->stream_id; |
---|
2576 | | - array++; |
---|
2577 | | - } |
---|
2578 | | - |
---|
2579 | | - if (type & PERF_SAMPLE_CPU) { |
---|
2580 | | - u.val32[0] = sample->cpu; |
---|
2581 | | - u.val32[1] = 0; |
---|
2582 | | - *array = u.val64; |
---|
2583 | | - array++; |
---|
2584 | | - } |
---|
2585 | | - |
---|
2586 | | - if (type & PERF_SAMPLE_PERIOD) { |
---|
2587 | | - *array = sample->period; |
---|
2588 | | - array++; |
---|
2589 | | - } |
---|
2590 | | - |
---|
2591 | | - if (type & PERF_SAMPLE_READ) { |
---|
2592 | | - if (read_format & PERF_FORMAT_GROUP) |
---|
2593 | | - *array = sample->read.group.nr; |
---|
2594 | | - else |
---|
2595 | | - *array = sample->read.one.value; |
---|
2596 | | - array++; |
---|
2597 | | - |
---|
2598 | | - if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) { |
---|
2599 | | - *array = sample->read.time_enabled; |
---|
2600 | | - array++; |
---|
2601 | | - } |
---|
2602 | | - |
---|
2603 | | - if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) { |
---|
2604 | | - *array = sample->read.time_running; |
---|
2605 | | - array++; |
---|
2606 | | - } |
---|
2607 | | - |
---|
2608 | | - /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */ |
---|
2609 | | - if (read_format & PERF_FORMAT_GROUP) { |
---|
2610 | | - sz = sample->read.group.nr * |
---|
2611 | | - sizeof(struct sample_read_value); |
---|
2612 | | - memcpy(array, sample->read.group.values, sz); |
---|
2613 | | - array = (void *)array + sz; |
---|
2614 | | - } else { |
---|
2615 | | - *array = sample->read.one.id; |
---|
2616 | | - array++; |
---|
2617 | | - } |
---|
2618 | | - } |
---|
2619 | | - |
---|
2620 | | - if (type & PERF_SAMPLE_CALLCHAIN) { |
---|
2621 | | - sz = (sample->callchain->nr + 1) * sizeof(u64); |
---|
2622 | | - memcpy(array, sample->callchain, sz); |
---|
2623 | | - array = (void *)array + sz; |
---|
2624 | | - } |
---|
2625 | | - |
---|
2626 | | - if (type & PERF_SAMPLE_RAW) { |
---|
2627 | | - u.val32[0] = sample->raw_size; |
---|
2628 | | - *array = u.val64; |
---|
2629 | | - array = (void *)array + sizeof(u32); |
---|
2630 | | - |
---|
2631 | | - memcpy(array, sample->raw_data, sample->raw_size); |
---|
2632 | | - array = (void *)array + sample->raw_size; |
---|
2633 | | - } |
---|
2634 | | - |
---|
2635 | | - if (type & PERF_SAMPLE_BRANCH_STACK) { |
---|
2636 | | - sz = sample->branch_stack->nr * sizeof(struct branch_entry); |
---|
2637 | | - sz += sizeof(u64); |
---|
2638 | | - memcpy(array, sample->branch_stack, sz); |
---|
2639 | | - array = (void *)array + sz; |
---|
2640 | | - } |
---|
2641 | | - |
---|
2642 | | - if (type & PERF_SAMPLE_REGS_USER) { |
---|
2643 | | - if (sample->user_regs.abi) { |
---|
2644 | | - *array++ = sample->user_regs.abi; |
---|
2645 | | - sz = hweight_long(sample->user_regs.mask) * sizeof(u64); |
---|
2646 | | - memcpy(array, sample->user_regs.regs, sz); |
---|
2647 | | - array = (void *)array + sz; |
---|
2648 | | - } else { |
---|
2649 | | - *array++ = 0; |
---|
2650 | | - } |
---|
2651 | | - } |
---|
2652 | | - |
---|
2653 | | - if (type & PERF_SAMPLE_STACK_USER) { |
---|
2654 | | - sz = sample->user_stack.size; |
---|
2655 | | - *array++ = sz; |
---|
2656 | | - if (sz) { |
---|
2657 | | - memcpy(array, sample->user_stack.data, sz); |
---|
2658 | | - array = (void *)array + sz; |
---|
2659 | | - *array++ = sz; |
---|
2660 | | - } |
---|
2661 | | - } |
---|
2662 | | - |
---|
2663 | | - if (type & PERF_SAMPLE_WEIGHT) { |
---|
2664 | | - *array = sample->weight; |
---|
2665 | | - array++; |
---|
2666 | | - } |
---|
2667 | | - |
---|
2668 | | - if (type & PERF_SAMPLE_DATA_SRC) { |
---|
2669 | | - *array = sample->data_src; |
---|
2670 | | - array++; |
---|
2671 | | - } |
---|
2672 | | - |
---|
2673 | | - if (type & PERF_SAMPLE_TRANSACTION) { |
---|
2674 | | - *array = sample->transaction; |
---|
2675 | | - array++; |
---|
2676 | | - } |
---|
2677 | | - |
---|
2678 | | - if (type & PERF_SAMPLE_REGS_INTR) { |
---|
2679 | | - if (sample->intr_regs.abi) { |
---|
2680 | | - *array++ = sample->intr_regs.abi; |
---|
2681 | | - sz = hweight_long(sample->intr_regs.mask) * sizeof(u64); |
---|
2682 | | - memcpy(array, sample->intr_regs.regs, sz); |
---|
2683 | | - array = (void *)array + sz; |
---|
2684 | | - } else { |
---|
2685 | | - *array++ = 0; |
---|
2686 | | - } |
---|
2687 | | - } |
---|
2688 | | - |
---|
2689 | | - if (type & PERF_SAMPLE_PHYS_ADDR) { |
---|
2690 | | - *array = sample->phys_addr; |
---|
2691 | | - array++; |
---|
2692 | | - } |
---|
2693 | | - |
---|
2694 | | - return 0; |
---|
2695 | | -} |
---|
2696 | | - |
---|
2697 | | -struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name) |
---|
| 2436 | +struct tep_format_field *evsel__field(struct evsel *evsel, const char *name) |
---|
2698 | 2437 | { |
---|
2699 | 2438 | return tep_find_field(evsel->tp_format, name); |
---|
2700 | 2439 | } |
---|
2701 | 2440 | |
---|
2702 | | -void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample, |
---|
2703 | | - const char *name) |
---|
| 2441 | +void *evsel__rawptr(struct evsel *evsel, struct perf_sample *sample, const char *name) |
---|
2704 | 2442 | { |
---|
2705 | | - struct format_field *field = perf_evsel__field(evsel, name); |
---|
| 2443 | + struct tep_format_field *field = evsel__field(evsel, name); |
---|
2706 | 2444 | int offset; |
---|
2707 | 2445 | |
---|
2708 | 2446 | if (!field) |
---|
.. | .. |
---|
2710 | 2448 | |
---|
2711 | 2449 | offset = field->offset; |
---|
2712 | 2450 | |
---|
2713 | | - if (field->flags & FIELD_IS_DYNAMIC) { |
---|
| 2451 | + if (field->flags & TEP_FIELD_IS_DYNAMIC) { |
---|
2714 | 2452 | offset = *(int *)(sample->raw_data + field->offset); |
---|
2715 | 2453 | offset &= 0xffff; |
---|
2716 | 2454 | } |
---|
.. | .. |
---|
2718 | 2456 | return sample->raw_data + offset; |
---|
2719 | 2457 | } |
---|
2720 | 2458 | |
---|
2721 | | -u64 format_field__intval(struct format_field *field, struct perf_sample *sample, |
---|
| 2459 | +u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sample, |
---|
2722 | 2460 | bool needs_swap) |
---|
2723 | 2461 | { |
---|
2724 | 2462 | u64 value; |
---|
.. | .. |
---|
2757 | 2495 | return 0; |
---|
2758 | 2496 | } |
---|
2759 | 2497 | |
---|
2760 | | -u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, |
---|
2761 | | - const char *name) |
---|
| 2498 | +u64 evsel__intval(struct evsel *evsel, struct perf_sample *sample, const char *name) |
---|
2762 | 2499 | { |
---|
2763 | | - struct format_field *field = perf_evsel__field(evsel, name); |
---|
| 2500 | + struct tep_format_field *field = evsel__field(evsel, name); |
---|
2764 | 2501 | |
---|
2765 | 2502 | if (!field) |
---|
2766 | 2503 | return 0; |
---|
.. | .. |
---|
2768 | 2505 | return field ? format_field__intval(field, sample, evsel->needs_swap) : 0; |
---|
2769 | 2506 | } |
---|
2770 | 2507 | |
---|
2771 | | -bool perf_evsel__fallback(struct perf_evsel *evsel, int err, |
---|
2772 | | - char *msg, size_t msgsize) |
---|
| 2508 | +bool evsel__fallback(struct evsel *evsel, int err, char *msg, size_t msgsize) |
---|
2773 | 2509 | { |
---|
2774 | 2510 | int paranoid; |
---|
2775 | 2511 | |
---|
2776 | 2512 | if ((err == ENOENT || err == ENXIO || err == ENODEV) && |
---|
2777 | | - evsel->attr.type == PERF_TYPE_HARDWARE && |
---|
2778 | | - evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES) { |
---|
| 2513 | + evsel->core.attr.type == PERF_TYPE_HARDWARE && |
---|
| 2514 | + evsel->core.attr.config == PERF_COUNT_HW_CPU_CYCLES) { |
---|
2779 | 2515 | /* |
---|
2780 | 2516 | * If it's cycles then fall back to hrtimer based |
---|
2781 | 2517 | * cpu-clock-tick sw counter, which is always available even if |
---|
.. | .. |
---|
2787 | 2523 | scnprintf(msg, msgsize, "%s", |
---|
2788 | 2524 | "The cycles event is not supported, trying to fall back to cpu-clock-ticks"); |
---|
2789 | 2525 | |
---|
2790 | | - evsel->attr.type = PERF_TYPE_SOFTWARE; |
---|
2791 | | - evsel->attr.config = PERF_COUNT_SW_CPU_CLOCK; |
---|
| 2526 | + evsel->core.attr.type = PERF_TYPE_SOFTWARE; |
---|
| 2527 | + evsel->core.attr.config = PERF_COUNT_SW_CPU_CLOCK; |
---|
2792 | 2528 | |
---|
2793 | 2529 | zfree(&evsel->name); |
---|
2794 | 2530 | return true; |
---|
2795 | | - } else if (err == EACCES && !evsel->attr.exclude_kernel && |
---|
| 2531 | + } else if (err == EACCES && !evsel->core.attr.exclude_kernel && |
---|
2796 | 2532 | (paranoid = perf_event_paranoid()) > 1) { |
---|
2797 | | - const char *name = perf_evsel__name(evsel); |
---|
| 2533 | + const char *name = evsel__name(evsel); |
---|
2798 | 2534 | char *new_name; |
---|
2799 | 2535 | const char *sep = ":"; |
---|
2800 | 2536 | |
---|
| 2537 | + /* If event has exclude user then don't exclude kernel. */ |
---|
| 2538 | + if (evsel->core.attr.exclude_user) |
---|
| 2539 | + return false; |
---|
| 2540 | + |
---|
2801 | 2541 | /* Is there already the separator in the name. */ |
---|
2802 | 2542 | if (strchr(name, '/') || |
---|
2803 | | - strchr(name, ':')) |
---|
| 2543 | + (strchr(name, ':') && !evsel->is_libpfm_event)) |
---|
2804 | 2544 | sep = ""; |
---|
2805 | 2545 | |
---|
2806 | 2546 | if (asprintf(&new_name, "%s%su", name, sep) < 0) |
---|
.. | .. |
---|
2809 | 2549 | if (evsel->name) |
---|
2810 | 2550 | free(evsel->name); |
---|
2811 | 2551 | evsel->name = new_name; |
---|
2812 | | - scnprintf(msg, msgsize, |
---|
2813 | | -"kernel.perf_event_paranoid=%d, trying to fall back to excluding kernel samples", paranoid); |
---|
2814 | | - evsel->attr.exclude_kernel = 1; |
---|
| 2552 | + scnprintf(msg, msgsize, "kernel.perf_event_paranoid=%d, trying " |
---|
| 2553 | + "to fall back to excluding kernel and hypervisor " |
---|
| 2554 | + " samples", paranoid); |
---|
| 2555 | + evsel->core.attr.exclude_kernel = 1; |
---|
| 2556 | + evsel->core.attr.exclude_hv = 1; |
---|
2815 | 2557 | |
---|
2816 | 2558 | return true; |
---|
2817 | 2559 | } |
---|
.. | .. |
---|
2855 | 2597 | return ret ? false : true; |
---|
2856 | 2598 | } |
---|
2857 | 2599 | |
---|
2858 | | -int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, |
---|
2859 | | - int err, char *msg, size_t size) |
---|
| 2600 | +int evsel__open_strerror(struct evsel *evsel, struct target *target, |
---|
| 2601 | + int err, char *msg, size_t size) |
---|
2860 | 2602 | { |
---|
2861 | 2603 | char sbuf[STRERR_BUFSIZE]; |
---|
2862 | | - int printed = 0; |
---|
| 2604 | + int printed = 0, enforced = 0; |
---|
2863 | 2605 | |
---|
2864 | 2606 | switch (err) { |
---|
2865 | 2607 | case EPERM: |
---|
2866 | 2608 | case EACCES: |
---|
| 2609 | + printed += scnprintf(msg + printed, size - printed, |
---|
| 2610 | + "Access to performance monitoring and observability operations is limited.\n"); |
---|
| 2611 | + |
---|
| 2612 | + if (!sysfs__read_int("fs/selinux/enforce", &enforced)) { |
---|
| 2613 | + if (enforced) { |
---|
| 2614 | + printed += scnprintf(msg + printed, size - printed, |
---|
| 2615 | + "Enforced MAC policy settings (SELinux) can limit access to performance\n" |
---|
| 2616 | + "monitoring and observability operations. Inspect system audit records for\n" |
---|
| 2617 | + "more perf_event access control information and adjusting the policy.\n"); |
---|
| 2618 | + } |
---|
| 2619 | + } |
---|
| 2620 | + |
---|
2867 | 2621 | if (err == EPERM) |
---|
2868 | | - printed = scnprintf(msg, size, |
---|
2869 | | - "No permission to enable %s event.\n\n", |
---|
2870 | | - perf_evsel__name(evsel)); |
---|
| 2622 | + printed += scnprintf(msg, size, |
---|
| 2623 | + "No permission to enable %s event.\n\n", evsel__name(evsel)); |
---|
2871 | 2624 | |
---|
2872 | 2625 | return scnprintf(msg + printed, size - printed, |
---|
2873 | | - "You may not have permission to collect %sstats.\n\n" |
---|
2874 | | - "Consider tweaking /proc/sys/kernel/perf_event_paranoid,\n" |
---|
2875 | | - "which controls use of the performance events system by\n" |
---|
2876 | | - "unprivileged users (without CAP_SYS_ADMIN).\n\n" |
---|
2877 | | - "The current value is %d:\n\n" |
---|
| 2626 | + "Consider adjusting /proc/sys/kernel/perf_event_paranoid setting to open\n" |
---|
| 2627 | + "access to performance monitoring and observability operations for processes\n" |
---|
| 2628 | + "without CAP_PERFMON, CAP_SYS_PTRACE or CAP_SYS_ADMIN Linux capability.\n" |
---|
| 2629 | + "More information can be found at 'Perf events and tool security' document:\n" |
---|
| 2630 | + "https://www.kernel.org/doc/html/latest/admin-guide/perf-security.html\n" |
---|
| 2631 | + "perf_event_paranoid setting is %d:\n" |
---|
2878 | 2632 | " -1: Allow use of (almost) all events by all users\n" |
---|
2879 | 2633 | " Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK\n" |
---|
2880 | | - ">= 0: Disallow ftrace function tracepoint by users without CAP_SYS_ADMIN\n" |
---|
2881 | | - " Disallow raw tracepoint access by users without CAP_SYS_ADMIN\n" |
---|
2882 | | - ">= 1: Disallow CPU event access by users without CAP_SYS_ADMIN\n" |
---|
2883 | | - ">= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN\n\n" |
---|
2884 | | - "To make this setting permanent, edit /etc/sysctl.conf too, e.g.:\n\n" |
---|
2885 | | - " kernel.perf_event_paranoid = -1\n" , |
---|
2886 | | - target->system_wide ? "system-wide " : "", |
---|
2887 | | - perf_event_paranoid()); |
---|
| 2634 | + ">= 0: Disallow raw and ftrace function tracepoint access\n" |
---|
| 2635 | + ">= 1: Disallow CPU event access\n" |
---|
| 2636 | + ">= 2: Disallow kernel profiling\n" |
---|
| 2637 | + "To make the adjusted perf_event_paranoid setting permanent preserve it\n" |
---|
| 2638 | + "in /etc/sysctl.conf (e.g. kernel.perf_event_paranoid = <setting>)", |
---|
| 2639 | + perf_event_paranoid()); |
---|
2888 | 2640 | case ENOENT: |
---|
2889 | | - return scnprintf(msg, size, "The %s event is not supported.", |
---|
2890 | | - perf_evsel__name(evsel)); |
---|
| 2641 | + return scnprintf(msg, size, "The %s event is not supported.", evsel__name(evsel)); |
---|
2891 | 2642 | case EMFILE: |
---|
2892 | 2643 | return scnprintf(msg, size, "%s", |
---|
2893 | 2644 | "Too many events are opened.\n" |
---|
.. | .. |
---|
2908 | 2659 | "No such device - did you specify an out-of-range profile CPU?"); |
---|
2909 | 2660 | break; |
---|
2910 | 2661 | case EOPNOTSUPP: |
---|
2911 | | - if (evsel->attr.sample_period != 0) |
---|
| 2662 | + if (evsel->core.attr.aux_output) |
---|
| 2663 | + return scnprintf(msg, size, |
---|
| 2664 | + "%s: PMU Hardware doesn't support 'aux_output' feature", |
---|
| 2665 | + evsel__name(evsel)); |
---|
| 2666 | + if (evsel->core.attr.sample_period != 0) |
---|
2912 | 2667 | return scnprintf(msg, size, |
---|
2913 | 2668 | "%s: PMU Hardware doesn't support sampling/overflow-interrupts. Try 'perf stat'", |
---|
2914 | | - perf_evsel__name(evsel)); |
---|
2915 | | - if (evsel->attr.precise_ip) |
---|
| 2669 | + evsel__name(evsel)); |
---|
| 2670 | + if (evsel->core.attr.precise_ip) |
---|
2916 | 2671 | return scnprintf(msg, size, "%s", |
---|
2917 | 2672 | "\'precise\' request may not be supported. Try removing 'p' modifier."); |
---|
2918 | 2673 | #if defined(__i386__) || defined(__x86_64__) |
---|
2919 | | - if (evsel->attr.type == PERF_TYPE_HARDWARE) |
---|
| 2674 | + if (evsel->core.attr.type == PERF_TYPE_HARDWARE) |
---|
2920 | 2675 | return scnprintf(msg, size, "%s", |
---|
2921 | 2676 | "No hardware sampling interrupt available.\n"); |
---|
2922 | 2677 | #endif |
---|
.. | .. |
---|
2928 | 2683 | "We found oprofile daemon running, please stop it and try again."); |
---|
2929 | 2684 | break; |
---|
2930 | 2685 | case EINVAL: |
---|
2931 | | - if (evsel->attr.write_backward && perf_missing_features.write_backward) |
---|
| 2686 | + if (evsel->core.attr.write_backward && perf_missing_features.write_backward) |
---|
2932 | 2687 | return scnprintf(msg, size, "Reading from overwrite event is not supported by this kernel."); |
---|
2933 | 2688 | if (perf_missing_features.clockid) |
---|
2934 | 2689 | return scnprintf(msg, size, "clockid feature not supported."); |
---|
2935 | 2690 | if (perf_missing_features.clockid_wrong) |
---|
2936 | 2691 | return scnprintf(msg, size, "wrong clockid (%d).", clockid); |
---|
| 2692 | + if (perf_missing_features.aux_output) |
---|
| 2693 | + return scnprintf(msg, size, "The 'aux_output' feature is not supported, update the kernel."); |
---|
2937 | 2694 | break; |
---|
2938 | 2695 | default: |
---|
2939 | 2696 | break; |
---|
.. | .. |
---|
2942 | 2699 | return scnprintf(msg, size, |
---|
2943 | 2700 | "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n" |
---|
2944 | 2701 | "/bin/dmesg | grep -i perf may provide additional information.\n", |
---|
2945 | | - err, str_error_r(err, sbuf, sizeof(sbuf)), |
---|
2946 | | - perf_evsel__name(evsel)); |
---|
| 2702 | + err, str_error_r(err, sbuf, sizeof(sbuf)), evsel__name(evsel)); |
---|
2947 | 2703 | } |
---|
2948 | 2704 | |
---|
2949 | | -struct perf_env *perf_evsel__env(struct perf_evsel *evsel) |
---|
| 2705 | +struct perf_env *evsel__env(struct evsel *evsel) |
---|
2950 | 2706 | { |
---|
2951 | 2707 | if (evsel && evsel->evlist) |
---|
2952 | 2708 | return evsel->evlist->env; |
---|
2953 | | - return NULL; |
---|
| 2709 | + return &perf_env; |
---|
| 2710 | +} |
---|
| 2711 | + |
---|
| 2712 | +static int store_evsel_ids(struct evsel *evsel, struct evlist *evlist) |
---|
| 2713 | +{ |
---|
| 2714 | + int cpu, thread; |
---|
| 2715 | + |
---|
| 2716 | + for (cpu = 0; cpu < xyarray__max_x(evsel->core.fd); cpu++) { |
---|
| 2717 | + for (thread = 0; thread < xyarray__max_y(evsel->core.fd); |
---|
| 2718 | + thread++) { |
---|
| 2719 | + int fd = FD(evsel, cpu, thread); |
---|
| 2720 | + |
---|
| 2721 | + if (perf_evlist__id_add_fd(&evlist->core, &evsel->core, |
---|
| 2722 | + cpu, thread, fd) < 0) |
---|
| 2723 | + return -1; |
---|
| 2724 | + } |
---|
| 2725 | + } |
---|
| 2726 | + |
---|
| 2727 | + return 0; |
---|
| 2728 | +} |
---|
| 2729 | + |
---|
| 2730 | +int evsel__store_ids(struct evsel *evsel, struct evlist *evlist) |
---|
| 2731 | +{ |
---|
| 2732 | + struct perf_cpu_map *cpus = evsel->core.cpus; |
---|
| 2733 | + struct perf_thread_map *threads = evsel->core.threads; |
---|
| 2734 | + |
---|
| 2735 | + if (perf_evsel__alloc_id(&evsel->core, cpus->nr, threads->nr)) |
---|
| 2736 | + return -ENOMEM; |
---|
| 2737 | + |
---|
| 2738 | + return store_evsel_ids(evsel, evlist); |
---|
2954 | 2739 | } |
---|