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 18 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 19 #define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0)) 20 21 int __perf_evsel__sample_size(u64 sample_type) 22 { 23 u64 mask = sample_type & PERF_SAMPLE_MASK; 24 int size = 0; 25 int i; 26 27 for (i = 0; i < 64; i++) { 28 if (mask & (1ULL << i)) 29 size++; 30 } 31 32 size *= sizeof(u64); 33 34 return size; 35 } 36 37 static void hists__init(struct hists *hists) 38 { 39 memset(hists, 0, sizeof(*hists)); 40 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT; 41 hists->entries_in = &hists->entries_in_array[0]; 42 hists->entries_collapsed = RB_ROOT; 43 hists->entries = RB_ROOT; 44 pthread_mutex_init(&hists->lock, NULL); 45 } 46 47 void perf_evsel__init(struct perf_evsel *evsel, 48 struct perf_event_attr *attr, int idx) 49 { 50 evsel->idx = idx; 51 evsel->attr = *attr; 52 INIT_LIST_HEAD(&evsel->node); 53 hists__init(&evsel->hists); 54 } 55 56 struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) 57 { 58 struct perf_evsel *evsel = zalloc(sizeof(*evsel)); 59 60 if (evsel != NULL) 61 perf_evsel__init(evsel, attr, idx); 62 63 return evsel; 64 } 65 66 void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts) 67 { 68 struct perf_event_attr *attr = &evsel->attr; 69 int track = !evsel->idx; /* only the first counter needs these */ 70 71 attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1; 72 attr->inherit = !opts->no_inherit; 73 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 74 PERF_FORMAT_TOTAL_TIME_RUNNING | 75 PERF_FORMAT_ID; 76 77 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; 78 79 /* 80 * We default some events to a 1 default interval. But keep 81 * it a weak assumption overridable by the user. 82 */ 83 if (!attr->sample_period || (opts->user_freq != UINT_MAX && 84 opts->user_interval != ULLONG_MAX)) { 85 if (opts->freq) { 86 attr->sample_type |= PERF_SAMPLE_PERIOD; 87 attr->freq = 1; 88 attr->sample_freq = opts->freq; 89 } else { 90 attr->sample_period = opts->default_interval; 91 } 92 } 93 94 if (opts->no_samples) 95 attr->sample_freq = 0; 96 97 if (opts->inherit_stat) 98 attr->inherit_stat = 1; 99 100 if (opts->sample_address) { 101 attr->sample_type |= PERF_SAMPLE_ADDR; 102 attr->mmap_data = track; 103 } 104 105 if (opts->call_graph) 106 attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 107 108 if (opts->system_wide) 109 attr->sample_type |= PERF_SAMPLE_CPU; 110 111 if (opts->period) 112 attr->sample_type |= PERF_SAMPLE_PERIOD; 113 114 if (!opts->sample_id_all_missing && 115 (opts->sample_time || opts->system_wide || 116 !opts->no_inherit || opts->cpu_list)) 117 attr->sample_type |= PERF_SAMPLE_TIME; 118 119 if (opts->raw_samples) { 120 attr->sample_type |= PERF_SAMPLE_TIME; 121 attr->sample_type |= PERF_SAMPLE_RAW; 122 attr->sample_type |= PERF_SAMPLE_CPU; 123 } 124 125 if (opts->no_delay) { 126 attr->watermark = 0; 127 attr->wakeup_events = 1; 128 } 129 if (opts->branch_stack) { 130 attr->sample_type |= PERF_SAMPLE_BRANCH_STACK; 131 attr->branch_sample_type = opts->branch_stack; 132 } 133 134 attr->mmap = track; 135 attr->comm = track; 136 137 if (!opts->target_pid && !opts->target_tid && !opts->system_wide) { 138 attr->disabled = 1; 139 attr->enable_on_exec = 1; 140 } 141 } 142 143 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 144 { 145 int cpu, thread; 146 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); 147 148 if (evsel->fd) { 149 for (cpu = 0; cpu < ncpus; cpu++) { 150 for (thread = 0; thread < nthreads; thread++) { 151 FD(evsel, cpu, thread) = -1; 152 } 153 } 154 } 155 156 return evsel->fd != NULL ? 0 : -ENOMEM; 157 } 158 159 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) 160 { 161 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); 162 if (evsel->sample_id == NULL) 163 return -ENOMEM; 164 165 evsel->id = zalloc(ncpus * nthreads * sizeof(u64)); 166 if (evsel->id == NULL) { 167 xyarray__delete(evsel->sample_id); 168 evsel->sample_id = NULL; 169 return -ENOMEM; 170 } 171 172 return 0; 173 } 174 175 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus) 176 { 177 evsel->counts = zalloc((sizeof(*evsel->counts) + 178 (ncpus * sizeof(struct perf_counts_values)))); 179 return evsel->counts != NULL ? 0 : -ENOMEM; 180 } 181 182 void perf_evsel__free_fd(struct perf_evsel *evsel) 183 { 184 xyarray__delete(evsel->fd); 185 evsel->fd = NULL; 186 } 187 188 void perf_evsel__free_id(struct perf_evsel *evsel) 189 { 190 xyarray__delete(evsel->sample_id); 191 evsel->sample_id = NULL; 192 free(evsel->id); 193 evsel->id = NULL; 194 } 195 196 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 197 { 198 int cpu, thread; 199 200 for (cpu = 0; cpu < ncpus; cpu++) 201 for (thread = 0; thread < nthreads; ++thread) { 202 close(FD(evsel, cpu, thread)); 203 FD(evsel, cpu, thread) = -1; 204 } 205 } 206 207 void perf_evsel__exit(struct perf_evsel *evsel) 208 { 209 assert(list_empty(&evsel->node)); 210 xyarray__delete(evsel->fd); 211 xyarray__delete(evsel->sample_id); 212 free(evsel->id); 213 } 214 215 void perf_evsel__delete(struct perf_evsel *evsel) 216 { 217 perf_evsel__exit(evsel); 218 close_cgroup(evsel->cgrp); 219 free(evsel->name); 220 free(evsel); 221 } 222 223 int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, 224 int cpu, int thread, bool scale) 225 { 226 struct perf_counts_values count; 227 size_t nv = scale ? 3 : 1; 228 229 if (FD(evsel, cpu, thread) < 0) 230 return -EINVAL; 231 232 if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0) 233 return -ENOMEM; 234 235 if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0) 236 return -errno; 237 238 if (scale) { 239 if (count.run == 0) 240 count.val = 0; 241 else if (count.run < count.ena) 242 count.val = (u64)((double)count.val * count.ena / count.run + 0.5); 243 } else 244 count.ena = count.run = 0; 245 246 evsel->counts->cpu[cpu] = count; 247 return 0; 248 } 249 250 int __perf_evsel__read(struct perf_evsel *evsel, 251 int ncpus, int nthreads, bool scale) 252 { 253 size_t nv = scale ? 3 : 1; 254 int cpu, thread; 255 struct perf_counts_values *aggr = &evsel->counts->aggr, count; 256 257 aggr->val = aggr->ena = aggr->run = 0; 258 259 for (cpu = 0; cpu < ncpus; cpu++) { 260 for (thread = 0; thread < nthreads; thread++) { 261 if (FD(evsel, cpu, thread) < 0) 262 continue; 263 264 if (readn(FD(evsel, cpu, thread), 265 &count, nv * sizeof(u64)) < 0) 266 return -errno; 267 268 aggr->val += count.val; 269 if (scale) { 270 aggr->ena += count.ena; 271 aggr->run += count.run; 272 } 273 } 274 } 275 276 evsel->counts->scaled = 0; 277 if (scale) { 278 if (aggr->run == 0) { 279 evsel->counts->scaled = -1; 280 aggr->val = 0; 281 return 0; 282 } 283 284 if (aggr->run < aggr->ena) { 285 evsel->counts->scaled = 1; 286 aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5); 287 } 288 } else 289 aggr->ena = aggr->run = 0; 290 291 return 0; 292 } 293 294 static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 295 struct thread_map *threads, bool group, 296 struct xyarray *group_fds) 297 { 298 int cpu, thread; 299 unsigned long flags = 0; 300 int pid = -1, err; 301 302 if (evsel->fd == NULL && 303 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) 304 return -ENOMEM; 305 306 if (evsel->cgrp) { 307 flags = PERF_FLAG_PID_CGROUP; 308 pid = evsel->cgrp->fd; 309 } 310 311 for (cpu = 0; cpu < cpus->nr; cpu++) { 312 int group_fd = group_fds ? GROUP_FD(group_fds, cpu) : -1; 313 314 for (thread = 0; thread < threads->nr; thread++) { 315 316 if (!evsel->cgrp) 317 pid = threads->map[thread]; 318 319 FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr, 320 pid, 321 cpus->map[cpu], 322 group_fd, flags); 323 if (FD(evsel, cpu, thread) < 0) { 324 err = -errno; 325 goto out_close; 326 } 327 328 if (group && group_fd == -1) 329 group_fd = FD(evsel, cpu, thread); 330 } 331 } 332 333 return 0; 334 335 out_close: 336 do { 337 while (--thread >= 0) { 338 close(FD(evsel, cpu, thread)); 339 FD(evsel, cpu, thread) = -1; 340 } 341 thread = threads->nr; 342 } while (--cpu >= 0); 343 return err; 344 } 345 346 void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads) 347 { 348 if (evsel->fd == NULL) 349 return; 350 351 perf_evsel__close_fd(evsel, ncpus, nthreads); 352 perf_evsel__free_fd(evsel); 353 evsel->fd = NULL; 354 } 355 356 static struct { 357 struct cpu_map map; 358 int cpus[1]; 359 } empty_cpu_map = { 360 .map.nr = 1, 361 .cpus = { -1, }, 362 }; 363 364 static struct { 365 struct thread_map map; 366 int threads[1]; 367 } empty_thread_map = { 368 .map.nr = 1, 369 .threads = { -1, }, 370 }; 371 372 int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 373 struct thread_map *threads, bool group, 374 struct xyarray *group_fd) 375 { 376 if (cpus == NULL) { 377 /* Work around old compiler warnings about strict aliasing */ 378 cpus = &empty_cpu_map.map; 379 } 380 381 if (threads == NULL) 382 threads = &empty_thread_map.map; 383 384 return __perf_evsel__open(evsel, cpus, threads, group, group_fd); 385 } 386 387 int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 388 struct cpu_map *cpus, bool group, 389 struct xyarray *group_fd) 390 { 391 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group, 392 group_fd); 393 } 394 395 int perf_evsel__open_per_thread(struct perf_evsel *evsel, 396 struct thread_map *threads, bool group, 397 struct xyarray *group_fd) 398 { 399 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group, 400 group_fd); 401 } 402 403 static int perf_event__parse_id_sample(const union perf_event *event, u64 type, 404 struct perf_sample *sample) 405 { 406 const u64 *array = event->sample.array; 407 408 array += ((event->header.size - 409 sizeof(event->header)) / sizeof(u64)) - 1; 410 411 if (type & PERF_SAMPLE_CPU) { 412 u32 *p = (u32 *)array; 413 sample->cpu = *p; 414 array--; 415 } 416 417 if (type & PERF_SAMPLE_STREAM_ID) { 418 sample->stream_id = *array; 419 array--; 420 } 421 422 if (type & PERF_SAMPLE_ID) { 423 sample->id = *array; 424 array--; 425 } 426 427 if (type & PERF_SAMPLE_TIME) { 428 sample->time = *array; 429 array--; 430 } 431 432 if (type & PERF_SAMPLE_TID) { 433 u32 *p = (u32 *)array; 434 sample->pid = p[0]; 435 sample->tid = p[1]; 436 } 437 438 return 0; 439 } 440 441 static bool sample_overlap(const union perf_event *event, 442 const void *offset, u64 size) 443 { 444 const void *base = event; 445 446 if (offset + size > base + event->header.size) 447 return true; 448 449 return false; 450 } 451 452 int perf_event__parse_sample(const union perf_event *event, u64 type, 453 int sample_size, bool sample_id_all, 454 struct perf_sample *data, bool swapped) 455 { 456 const u64 *array; 457 458 /* 459 * used for cross-endian analysis. See git commit 65014ab3 460 * for why this goofiness is needed. 461 */ 462 union { 463 u64 val64; 464 u32 val32[2]; 465 } 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 583 if (type & PERF_SAMPLE_BRANCH_STACK) { 584 u64 sz; 585 586 data->branch_stack = (struct branch_stack *)array; 587 array++; /* nr */ 588 589 sz = data->branch_stack->nr * sizeof(struct branch_entry); 590 sz /= sizeof(u64); 591 array += sz; 592 } 593 return 0; 594 } 595 596 int perf_event__synthesize_sample(union perf_event *event, u64 type, 597 const struct perf_sample *sample, 598 bool swapped) 599 { 600 u64 *array; 601 602 /* 603 * used for cross-endian analysis. See git commit 65014ab3 604 * for why this goofiness is needed. 605 */ 606 union { 607 u64 val64; 608 u32 val32[2]; 609 } u; 610 611 array = event->sample.array; 612 613 if (type & PERF_SAMPLE_IP) { 614 event->ip.ip = sample->ip; 615 array++; 616 } 617 618 if (type & PERF_SAMPLE_TID) { 619 u.val32[0] = sample->pid; 620 u.val32[1] = sample->tid; 621 if (swapped) { 622 /* 623 * Inverse of what is done in perf_event__parse_sample 624 */ 625 u.val32[0] = bswap_32(u.val32[0]); 626 u.val32[1] = bswap_32(u.val32[1]); 627 u.val64 = bswap_64(u.val64); 628 } 629 630 *array = u.val64; 631 array++; 632 } 633 634 if (type & PERF_SAMPLE_TIME) { 635 *array = sample->time; 636 array++; 637 } 638 639 if (type & PERF_SAMPLE_ADDR) { 640 *array = sample->addr; 641 array++; 642 } 643 644 if (type & PERF_SAMPLE_ID) { 645 *array = sample->id; 646 array++; 647 } 648 649 if (type & PERF_SAMPLE_STREAM_ID) { 650 *array = sample->stream_id; 651 array++; 652 } 653 654 if (type & PERF_SAMPLE_CPU) { 655 u.val32[0] = sample->cpu; 656 if (swapped) { 657 /* 658 * Inverse of what is done in perf_event__parse_sample 659 */ 660 u.val32[0] = bswap_32(u.val32[0]); 661 u.val64 = bswap_64(u.val64); 662 } 663 *array = u.val64; 664 array++; 665 } 666 667 if (type & PERF_SAMPLE_PERIOD) { 668 *array = sample->period; 669 array++; 670 } 671 672 return 0; 673 } 674