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 (opts->target.system_wide) 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 { 466 u64 val64; 467 u32 val32[2]; 468 } u; 469 470 memset(data, 0, sizeof(*data)); 471 data->cpu = data->pid = data->tid = -1; 472 data->stream_id = data->id = data->time = -1ULL; 473 data->period = 1; 474 475 if (event->header.type != PERF_RECORD_SAMPLE) { 476 if (!sample_id_all) 477 return 0; 478 return perf_event__parse_id_sample(event, type, data); 479 } 480 481 array = event->sample.array; 482 483 if (sample_size + sizeof(event->header) > event->header.size) 484 return -EFAULT; 485 486 if (type & PERF_SAMPLE_IP) { 487 data->ip = event->ip.ip; 488 array++; 489 } 490 491 if (type & PERF_SAMPLE_TID) { 492 u.val64 = *array; 493 if (swapped) { 494 /* undo swap of u64, then swap on individual u32s */ 495 u.val64 = bswap_64(u.val64); 496 u.val32[0] = bswap_32(u.val32[0]); 497 u.val32[1] = bswap_32(u.val32[1]); 498 } 499 500 data->pid = u.val32[0]; 501 data->tid = u.val32[1]; 502 array++; 503 } 504 505 if (type & PERF_SAMPLE_TIME) { 506 data->time = *array; 507 array++; 508 } 509 510 data->addr = 0; 511 if (type & PERF_SAMPLE_ADDR) { 512 data->addr = *array; 513 array++; 514 } 515 516 data->id = -1ULL; 517 if (type & PERF_SAMPLE_ID) { 518 data->id = *array; 519 array++; 520 } 521 522 if (type & PERF_SAMPLE_STREAM_ID) { 523 data->stream_id = *array; 524 array++; 525 } 526 527 if (type & PERF_SAMPLE_CPU) { 528 529 u.val64 = *array; 530 if (swapped) { 531 /* undo swap of u64, then swap on individual u32s */ 532 u.val64 = bswap_64(u.val64); 533 u.val32[0] = bswap_32(u.val32[0]); 534 } 535 536 data->cpu = u.val32[0]; 537 array++; 538 } 539 540 if (type & PERF_SAMPLE_PERIOD) { 541 data->period = *array; 542 array++; 543 } 544 545 if (type & PERF_SAMPLE_READ) { 546 fprintf(stderr, "PERF_SAMPLE_READ is unsupported for now\n"); 547 return -1; 548 } 549 550 if (type & PERF_SAMPLE_CALLCHAIN) { 551 if (sample_overlap(event, array, sizeof(data->callchain->nr))) 552 return -EFAULT; 553 554 data->callchain = (struct ip_callchain *)array; 555 556 if (sample_overlap(event, array, data->callchain->nr)) 557 return -EFAULT; 558 559 array += 1 + data->callchain->nr; 560 } 561 562 if (type & PERF_SAMPLE_RAW) { 563 const u64 *pdata; 564 565 u.val64 = *array; 566 if (WARN_ONCE(swapped, 567 "Endianness of raw data not corrected!\n")) { 568 /* undo swap of u64, then swap on individual u32s */ 569 u.val64 = bswap_64(u.val64); 570 u.val32[0] = bswap_32(u.val32[0]); 571 u.val32[1] = bswap_32(u.val32[1]); 572 } 573 574 if (sample_overlap(event, array, sizeof(u32))) 575 return -EFAULT; 576 577 data->raw_size = u.val32[0]; 578 pdata = (void *) array + sizeof(u32); 579 580 if (sample_overlap(event, pdata, data->raw_size)) 581 return -EFAULT; 582 583 data->raw_data = (void *) pdata; 584 585 array = (void *)array + data->raw_size + sizeof(u32); 586 } 587 588 if (type & PERF_SAMPLE_BRANCH_STACK) { 589 u64 sz; 590 591 data->branch_stack = (struct branch_stack *)array; 592 array++; /* nr */ 593 594 sz = data->branch_stack->nr * sizeof(struct branch_entry); 595 sz /= sizeof(u64); 596 array += sz; 597 } 598 return 0; 599 } 600 601 int perf_event__synthesize_sample(union perf_event *event, u64 type, 602 const struct perf_sample *sample, 603 bool swapped) 604 { 605 u64 *array; 606 607 /* 608 * used for cross-endian analysis. See git commit 65014ab3 609 * for why this goofiness is needed. 610 */ 611 union { 612 u64 val64; 613 u32 val32[2]; 614 } u; 615 616 array = event->sample.array; 617 618 if (type & PERF_SAMPLE_IP) { 619 event->ip.ip = sample->ip; 620 array++; 621 } 622 623 if (type & PERF_SAMPLE_TID) { 624 u.val32[0] = sample->pid; 625 u.val32[1] = sample->tid; 626 if (swapped) { 627 /* 628 * Inverse of what is done in perf_event__parse_sample 629 */ 630 u.val32[0] = bswap_32(u.val32[0]); 631 u.val32[1] = bswap_32(u.val32[1]); 632 u.val64 = bswap_64(u.val64); 633 } 634 635 *array = u.val64; 636 array++; 637 } 638 639 if (type & PERF_SAMPLE_TIME) { 640 *array = sample->time; 641 array++; 642 } 643 644 if (type & PERF_SAMPLE_ADDR) { 645 *array = sample->addr; 646 array++; 647 } 648 649 if (type & PERF_SAMPLE_ID) { 650 *array = sample->id; 651 array++; 652 } 653 654 if (type & PERF_SAMPLE_STREAM_ID) { 655 *array = sample->stream_id; 656 array++; 657 } 658 659 if (type & PERF_SAMPLE_CPU) { 660 u.val32[0] = sample->cpu; 661 if (swapped) { 662 /* 663 * Inverse of what is done in perf_event__parse_sample 664 */ 665 u.val32[0] = bswap_32(u.val32[0]); 666 u.val64 = bswap_64(u.val64); 667 } 668 *array = u.val64; 669 array++; 670 } 671 672 if (type & PERF_SAMPLE_PERIOD) { 673 *array = sample->period; 674 array++; 675 } 676 677 return 0; 678 } 679