1 /* 2 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 3 * 4 * Parts came from builtin-{top,stat,record}.c, see those files for further 5 * copyright notes. 6 * 7 * Released under the GPL v2. (and only v2, not any later version) 8 */ 9 10 #include <byteswap.h> 11 #include "asm/bug.h" 12 #include "evsel.h" 13 #include "evlist.h" 14 #include "util.h" 15 #include "cpumap.h" 16 #include "thread_map.h" 17 #include "target.h" 18 19 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 20 #define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0)) 21 22 int __perf_evsel__sample_size(u64 sample_type) 23 { 24 u64 mask = sample_type & PERF_SAMPLE_MASK; 25 int size = 0; 26 int i; 27 28 for (i = 0; i < 64; i++) { 29 if (mask & (1ULL << i)) 30 size++; 31 } 32 33 size *= sizeof(u64); 34 35 return size; 36 } 37 38 void hists__init(struct hists *hists) 39 { 40 memset(hists, 0, sizeof(*hists)); 41 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT; 42 hists->entries_in = &hists->entries_in_array[0]; 43 hists->entries_collapsed = RB_ROOT; 44 hists->entries = RB_ROOT; 45 pthread_mutex_init(&hists->lock, NULL); 46 } 47 48 void perf_evsel__init(struct perf_evsel *evsel, 49 struct perf_event_attr *attr, int idx) 50 { 51 evsel->idx = idx; 52 evsel->attr = *attr; 53 INIT_LIST_HEAD(&evsel->node); 54 hists__init(&evsel->hists); 55 } 56 57 struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) 58 { 59 struct perf_evsel *evsel = zalloc(sizeof(*evsel)); 60 61 if (evsel != NULL) 62 perf_evsel__init(evsel, attr, idx); 63 64 return evsel; 65 } 66 67 void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts, 68 struct perf_evsel *first) 69 { 70 struct perf_event_attr *attr = &evsel->attr; 71 int track = !evsel->idx; /* only the first counter needs these */ 72 73 attr->disabled = 1; 74 attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1; 75 attr->inherit = !opts->no_inherit; 76 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 77 PERF_FORMAT_TOTAL_TIME_RUNNING | 78 PERF_FORMAT_ID; 79 80 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; 81 82 /* 83 * We default some events to a 1 default interval. But keep 84 * it a weak assumption overridable by the user. 85 */ 86 if (!attr->sample_period || (opts->user_freq != UINT_MAX && 87 opts->user_interval != ULLONG_MAX)) { 88 if (opts->freq) { 89 attr->sample_type |= PERF_SAMPLE_PERIOD; 90 attr->freq = 1; 91 attr->sample_freq = opts->freq; 92 } else { 93 attr->sample_period = opts->default_interval; 94 } 95 } 96 97 if (opts->no_samples) 98 attr->sample_freq = 0; 99 100 if (opts->inherit_stat) 101 attr->inherit_stat = 1; 102 103 if (opts->sample_address) { 104 attr->sample_type |= PERF_SAMPLE_ADDR; 105 attr->mmap_data = track; 106 } 107 108 if (opts->call_graph) 109 attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 110 111 if (perf_target__has_cpu(&opts->target)) 112 attr->sample_type |= PERF_SAMPLE_CPU; 113 114 if (opts->period) 115 attr->sample_type |= PERF_SAMPLE_PERIOD; 116 117 if (!opts->sample_id_all_missing && 118 (opts->sample_time || !opts->no_inherit || 119 perf_target__has_cpu(&opts->target))) 120 attr->sample_type |= PERF_SAMPLE_TIME; 121 122 if (opts->raw_samples) { 123 attr->sample_type |= PERF_SAMPLE_TIME; 124 attr->sample_type |= PERF_SAMPLE_RAW; 125 attr->sample_type |= PERF_SAMPLE_CPU; 126 } 127 128 if (opts->no_delay) { 129 attr->watermark = 0; 130 attr->wakeup_events = 1; 131 } 132 if (opts->branch_stack) { 133 attr->sample_type |= PERF_SAMPLE_BRANCH_STACK; 134 attr->branch_sample_type = opts->branch_stack; 135 } 136 137 attr->mmap = track; 138 attr->comm = track; 139 140 if (perf_target__none(&opts->target) && 141 (!opts->group || evsel == first)) { 142 attr->enable_on_exec = 1; 143 } 144 } 145 146 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 147 { 148 int cpu, thread; 149 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); 150 151 if (evsel->fd) { 152 for (cpu = 0; cpu < ncpus; cpu++) { 153 for (thread = 0; thread < nthreads; thread++) { 154 FD(evsel, cpu, thread) = -1; 155 } 156 } 157 } 158 159 return evsel->fd != NULL ? 0 : -ENOMEM; 160 } 161 162 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) 163 { 164 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); 165 if (evsel->sample_id == NULL) 166 return -ENOMEM; 167 168 evsel->id = zalloc(ncpus * nthreads * sizeof(u64)); 169 if (evsel->id == NULL) { 170 xyarray__delete(evsel->sample_id); 171 evsel->sample_id = NULL; 172 return -ENOMEM; 173 } 174 175 return 0; 176 } 177 178 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus) 179 { 180 evsel->counts = zalloc((sizeof(*evsel->counts) + 181 (ncpus * sizeof(struct perf_counts_values)))); 182 return evsel->counts != NULL ? 0 : -ENOMEM; 183 } 184 185 void perf_evsel__free_fd(struct perf_evsel *evsel) 186 { 187 xyarray__delete(evsel->fd); 188 evsel->fd = NULL; 189 } 190 191 void perf_evsel__free_id(struct perf_evsel *evsel) 192 { 193 xyarray__delete(evsel->sample_id); 194 evsel->sample_id = NULL; 195 free(evsel->id); 196 evsel->id = NULL; 197 } 198 199 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 200 { 201 int cpu, thread; 202 203 for (cpu = 0; cpu < ncpus; cpu++) 204 for (thread = 0; thread < nthreads; ++thread) { 205 close(FD(evsel, cpu, thread)); 206 FD(evsel, cpu, thread) = -1; 207 } 208 } 209 210 void perf_evsel__exit(struct perf_evsel *evsel) 211 { 212 assert(list_empty(&evsel->node)); 213 xyarray__delete(evsel->fd); 214 xyarray__delete(evsel->sample_id); 215 free(evsel->id); 216 } 217 218 void perf_evsel__delete(struct perf_evsel *evsel) 219 { 220 perf_evsel__exit(evsel); 221 close_cgroup(evsel->cgrp); 222 free(evsel->name); 223 free(evsel); 224 } 225 226 int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, 227 int cpu, int thread, bool scale) 228 { 229 struct perf_counts_values count; 230 size_t nv = scale ? 3 : 1; 231 232 if (FD(evsel, cpu, thread) < 0) 233 return -EINVAL; 234 235 if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0) 236 return -ENOMEM; 237 238 if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0) 239 return -errno; 240 241 if (scale) { 242 if (count.run == 0) 243 count.val = 0; 244 else if (count.run < count.ena) 245 count.val = (u64)((double)count.val * count.ena / count.run + 0.5); 246 } else 247 count.ena = count.run = 0; 248 249 evsel->counts->cpu[cpu] = count; 250 return 0; 251 } 252 253 int __perf_evsel__read(struct perf_evsel *evsel, 254 int ncpus, int nthreads, bool scale) 255 { 256 size_t nv = scale ? 3 : 1; 257 int cpu, thread; 258 struct perf_counts_values *aggr = &evsel->counts->aggr, count; 259 260 aggr->val = aggr->ena = aggr->run = 0; 261 262 for (cpu = 0; cpu < ncpus; cpu++) { 263 for (thread = 0; thread < nthreads; thread++) { 264 if (FD(evsel, cpu, thread) < 0) 265 continue; 266 267 if (readn(FD(evsel, cpu, thread), 268 &count, nv * sizeof(u64)) < 0) 269 return -errno; 270 271 aggr->val += count.val; 272 if (scale) { 273 aggr->ena += count.ena; 274 aggr->run += count.run; 275 } 276 } 277 } 278 279 evsel->counts->scaled = 0; 280 if (scale) { 281 if (aggr->run == 0) { 282 evsel->counts->scaled = -1; 283 aggr->val = 0; 284 return 0; 285 } 286 287 if (aggr->run < aggr->ena) { 288 evsel->counts->scaled = 1; 289 aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5); 290 } 291 } else 292 aggr->ena = aggr->run = 0; 293 294 return 0; 295 } 296 297 static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 298 struct thread_map *threads, bool group, 299 struct xyarray *group_fds) 300 { 301 int cpu, thread; 302 unsigned long flags = 0; 303 int pid = -1, err; 304 305 if (evsel->fd == NULL && 306 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) 307 return -ENOMEM; 308 309 if (evsel->cgrp) { 310 flags = PERF_FLAG_PID_CGROUP; 311 pid = evsel->cgrp->fd; 312 } 313 314 for (cpu = 0; cpu < cpus->nr; cpu++) { 315 int group_fd = group_fds ? GROUP_FD(group_fds, cpu) : -1; 316 317 for (thread = 0; thread < threads->nr; thread++) { 318 319 if (!evsel->cgrp) 320 pid = threads->map[thread]; 321 322 FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr, 323 pid, 324 cpus->map[cpu], 325 group_fd, flags); 326 if (FD(evsel, cpu, thread) < 0) { 327 err = -errno; 328 goto out_close; 329 } 330 331 if (group && group_fd == -1) 332 group_fd = FD(evsel, cpu, thread); 333 } 334 } 335 336 return 0; 337 338 out_close: 339 do { 340 while (--thread >= 0) { 341 close(FD(evsel, cpu, thread)); 342 FD(evsel, cpu, thread) = -1; 343 } 344 thread = threads->nr; 345 } while (--cpu >= 0); 346 return err; 347 } 348 349 void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads) 350 { 351 if (evsel->fd == NULL) 352 return; 353 354 perf_evsel__close_fd(evsel, ncpus, nthreads); 355 perf_evsel__free_fd(evsel); 356 evsel->fd = NULL; 357 } 358 359 static struct { 360 struct cpu_map map; 361 int cpus[1]; 362 } empty_cpu_map = { 363 .map.nr = 1, 364 .cpus = { -1, }, 365 }; 366 367 static struct { 368 struct thread_map map; 369 int threads[1]; 370 } empty_thread_map = { 371 .map.nr = 1, 372 .threads = { -1, }, 373 }; 374 375 int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 376 struct thread_map *threads, bool group, 377 struct xyarray *group_fd) 378 { 379 if (cpus == NULL) { 380 /* Work around old compiler warnings about strict aliasing */ 381 cpus = &empty_cpu_map.map; 382 } 383 384 if (threads == NULL) 385 threads = &empty_thread_map.map; 386 387 return __perf_evsel__open(evsel, cpus, threads, group, group_fd); 388 } 389 390 int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 391 struct cpu_map *cpus, bool group, 392 struct xyarray *group_fd) 393 { 394 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group, 395 group_fd); 396 } 397 398 int perf_evsel__open_per_thread(struct perf_evsel *evsel, 399 struct thread_map *threads, bool group, 400 struct xyarray *group_fd) 401 { 402 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group, 403 group_fd); 404 } 405 406 static int perf_event__parse_id_sample(const union perf_event *event, u64 type, 407 struct perf_sample *sample) 408 { 409 const u64 *array = event->sample.array; 410 411 array += ((event->header.size - 412 sizeof(event->header)) / sizeof(u64)) - 1; 413 414 if (type & PERF_SAMPLE_CPU) { 415 u32 *p = (u32 *)array; 416 sample->cpu = *p; 417 array--; 418 } 419 420 if (type & PERF_SAMPLE_STREAM_ID) { 421 sample->stream_id = *array; 422 array--; 423 } 424 425 if (type & PERF_SAMPLE_ID) { 426 sample->id = *array; 427 array--; 428 } 429 430 if (type & PERF_SAMPLE_TIME) { 431 sample->time = *array; 432 array--; 433 } 434 435 if (type & PERF_SAMPLE_TID) { 436 u32 *p = (u32 *)array; 437 sample->pid = p[0]; 438 sample->tid = p[1]; 439 } 440 441 return 0; 442 } 443 444 static bool sample_overlap(const union perf_event *event, 445 const void *offset, u64 size) 446 { 447 const void *base = event; 448 449 if (offset + size > base + event->header.size) 450 return true; 451 452 return false; 453 } 454 455 int perf_event__parse_sample(const union perf_event *event, u64 type, 456 int sample_size, bool sample_id_all, 457 struct perf_sample *data, bool swapped) 458 { 459 const u64 *array; 460 461 /* 462 * used for cross-endian analysis. See git commit 65014ab3 463 * for why this goofiness is needed. 464 */ 465 union u64_swap u; 466 467 memset(data, 0, sizeof(*data)); 468 data->cpu = data->pid = data->tid = -1; 469 data->stream_id = data->id = data->time = -1ULL; 470 data->period = 1; 471 472 if (event->header.type != PERF_RECORD_SAMPLE) { 473 if (!sample_id_all) 474 return 0; 475 return perf_event__parse_id_sample(event, type, data); 476 } 477 478 array = event->sample.array; 479 480 if (sample_size + sizeof(event->header) > event->header.size) 481 return -EFAULT; 482 483 if (type & PERF_SAMPLE_IP) { 484 data->ip = event->ip.ip; 485 array++; 486 } 487 488 if (type & PERF_SAMPLE_TID) { 489 u.val64 = *array; 490 if (swapped) { 491 /* undo swap of u64, then swap on individual u32s */ 492 u.val64 = bswap_64(u.val64); 493 u.val32[0] = bswap_32(u.val32[0]); 494 u.val32[1] = bswap_32(u.val32[1]); 495 } 496 497 data->pid = u.val32[0]; 498 data->tid = u.val32[1]; 499 array++; 500 } 501 502 if (type & PERF_SAMPLE_TIME) { 503 data->time = *array; 504 array++; 505 } 506 507 data->addr = 0; 508 if (type & PERF_SAMPLE_ADDR) { 509 data->addr = *array; 510 array++; 511 } 512 513 data->id = -1ULL; 514 if (type & PERF_SAMPLE_ID) { 515 data->id = *array; 516 array++; 517 } 518 519 if (type & PERF_SAMPLE_STREAM_ID) { 520 data->stream_id = *array; 521 array++; 522 } 523 524 if (type & PERF_SAMPLE_CPU) { 525 526 u.val64 = *array; 527 if (swapped) { 528 /* undo swap of u64, then swap on individual u32s */ 529 u.val64 = bswap_64(u.val64); 530 u.val32[0] = bswap_32(u.val32[0]); 531 } 532 533 data->cpu = u.val32[0]; 534 array++; 535 } 536 537 if (type & PERF_SAMPLE_PERIOD) { 538 data->period = *array; 539 array++; 540 } 541 542 if (type & PERF_SAMPLE_READ) { 543 fprintf(stderr, "PERF_SAMPLE_READ is unsupported for now\n"); 544 return -1; 545 } 546 547 if (type & PERF_SAMPLE_CALLCHAIN) { 548 if (sample_overlap(event, array, sizeof(data->callchain->nr))) 549 return -EFAULT; 550 551 data->callchain = (struct ip_callchain *)array; 552 553 if (sample_overlap(event, array, data->callchain->nr)) 554 return -EFAULT; 555 556 array += 1 + data->callchain->nr; 557 } 558 559 if (type & PERF_SAMPLE_RAW) { 560 const u64 *pdata; 561 562 u.val64 = *array; 563 if (WARN_ONCE(swapped, 564 "Endianness of raw data not corrected!\n")) { 565 /* undo swap of u64, then swap on individual u32s */ 566 u.val64 = bswap_64(u.val64); 567 u.val32[0] = bswap_32(u.val32[0]); 568 u.val32[1] = bswap_32(u.val32[1]); 569 } 570 571 if (sample_overlap(event, array, sizeof(u32))) 572 return -EFAULT; 573 574 data->raw_size = u.val32[0]; 575 pdata = (void *) array + sizeof(u32); 576 577 if (sample_overlap(event, pdata, data->raw_size)) 578 return -EFAULT; 579 580 data->raw_data = (void *) pdata; 581 582 array = (void *)array + data->raw_size + sizeof(u32); 583 } 584 585 if (type & PERF_SAMPLE_BRANCH_STACK) { 586 u64 sz; 587 588 data->branch_stack = (struct branch_stack *)array; 589 array++; /* nr */ 590 591 sz = data->branch_stack->nr * sizeof(struct branch_entry); 592 sz /= sizeof(u64); 593 array += sz; 594 } 595 return 0; 596 } 597 598 int perf_event__synthesize_sample(union perf_event *event, u64 type, 599 const struct perf_sample *sample, 600 bool swapped) 601 { 602 u64 *array; 603 604 /* 605 * used for cross-endian analysis. See git commit 65014ab3 606 * for why this goofiness is needed. 607 */ 608 union u64_swap u; 609 610 array = event->sample.array; 611 612 if (type & PERF_SAMPLE_IP) { 613 event->ip.ip = sample->ip; 614 array++; 615 } 616 617 if (type & PERF_SAMPLE_TID) { 618 u.val32[0] = sample->pid; 619 u.val32[1] = sample->tid; 620 if (swapped) { 621 /* 622 * Inverse of what is done in perf_event__parse_sample 623 */ 624 u.val32[0] = bswap_32(u.val32[0]); 625 u.val32[1] = bswap_32(u.val32[1]); 626 u.val64 = bswap_64(u.val64); 627 } 628 629 *array = u.val64; 630 array++; 631 } 632 633 if (type & PERF_SAMPLE_TIME) { 634 *array = sample->time; 635 array++; 636 } 637 638 if (type & PERF_SAMPLE_ADDR) { 639 *array = sample->addr; 640 array++; 641 } 642 643 if (type & PERF_SAMPLE_ID) { 644 *array = sample->id; 645 array++; 646 } 647 648 if (type & PERF_SAMPLE_STREAM_ID) { 649 *array = sample->stream_id; 650 array++; 651 } 652 653 if (type & PERF_SAMPLE_CPU) { 654 u.val32[0] = sample->cpu; 655 if (swapped) { 656 /* 657 * Inverse of what is done in perf_event__parse_sample 658 */ 659 u.val32[0] = bswap_32(u.val32[0]); 660 u.val64 = bswap_64(u.val64); 661 } 662 *array = u.val64; 663 array++; 664 } 665 666 if (type & PERF_SAMPLE_PERIOD) { 667 *array = sample->period; 668 array++; 669 } 670 671 return 0; 672 } 673