diff options
| -rw-r--r-- | tools/lib/traceevent/event-parse.c | 17 | ||||
| -rw-r--r-- | tools/perf/Documentation/perf-list.txt | 1 | ||||
| -rw-r--r-- | tools/perf/Documentation/perf-record.txt | 7 | ||||
| -rw-r--r-- | tools/perf/builtin-kmem.c | 3 | ||||
| -rw-r--r-- | tools/perf/builtin-record.c | 87 | ||||
| -rw-r--r-- | tools/perf/builtin-report.c | 2 | ||||
| -rw-r--r-- | tools/perf/builtin-sched.c | 67 | ||||
| -rw-r--r-- | tools/perf/perf.h | 2 | ||||
| -rw-r--r-- | tools/perf/tests/attr/base-record | 2 | ||||
| -rw-r--r-- | tools/perf/tests/attr/base-stat | 2 | ||||
| -rw-r--r-- | tools/perf/tests/parse-events.c | 40 | ||||
| -rw-r--r-- | tools/perf/util/evlist.c | 2 | ||||
| -rw-r--r-- | tools/perf/util/evsel.c | 325 | ||||
| -rw-r--r-- | tools/perf/util/evsel.h | 6 | ||||
| -rw-r--r-- | tools/perf/util/header.c | 28 | ||||
| -rw-r--r-- | tools/perf/util/machine.c | 5 | ||||
| -rw-r--r-- | tools/perf/util/map.c | 20 | ||||
| -rw-r--r-- | tools/perf/util/map.h | 6 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.c | 8 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.l | 2 | ||||
| -rw-r--r-- | tools/perf/util/probe-event.c | 5 | ||||
| -rw-r--r-- | tools/perf/util/session.c | 3 | ||||
| -rw-r--r-- | tools/perf/util/symbol-elf.c | 16 | ||||
| -rw-r--r-- | tools/perf/util/symbol.c | 34 |
24 files changed, 477 insertions, 213 deletions
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 6d31b6419d37..12a7e2a40c89 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c | |||
| @@ -1939,7 +1939,22 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) | |||
| 1939 | goto out_warn_free; | 1939 | goto out_warn_free; |
| 1940 | 1940 | ||
| 1941 | type = process_arg_token(event, right, tok, type); | 1941 | type = process_arg_token(event, right, tok, type); |
| 1942 | arg->op.right = right; | 1942 | |
| 1943 | if (right->type == PRINT_OP && | ||
| 1944 | get_op_prio(arg->op.op) < get_op_prio(right->op.op)) { | ||
| 1945 | struct print_arg tmp; | ||
| 1946 | |||
| 1947 | /* rotate ops according to the priority */ | ||
| 1948 | arg->op.right = right->op.left; | ||
| 1949 | |||
| 1950 | tmp = *arg; | ||
| 1951 | *arg = *right; | ||
| 1952 | *right = tmp; | ||
| 1953 | |||
| 1954 | arg->op.left = right; | ||
| 1955 | } else { | ||
| 1956 | arg->op.right = right; | ||
| 1957 | } | ||
| 1943 | 1958 | ||
| 1944 | } else if (strcmp(token, "[") == 0) { | 1959 | } else if (strcmp(token, "[") == 0) { |
| 1945 | 1960 | ||
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt index 4692d277980b..bada8933fdd4 100644 --- a/tools/perf/Documentation/perf-list.txt +++ b/tools/perf/Documentation/perf-list.txt | |||
| @@ -26,6 +26,7 @@ counted. The following modifiers exist: | |||
| 26 | u - user-space counting | 26 | u - user-space counting |
| 27 | k - kernel counting | 27 | k - kernel counting |
| 28 | h - hypervisor counting | 28 | h - hypervisor counting |
| 29 | I - non idle counting | ||
| 29 | G - guest counting (in KVM guests) | 30 | G - guest counting (in KVM guests) |
| 30 | H - host counting (not in KVM guests) | 31 | H - host counting (not in KVM guests) |
| 31 | p - precise level | 32 | p - precise level |
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 355c4f5569b5..4847a793de65 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt | |||
| @@ -250,6 +250,13 @@ is off by default. | |||
| 250 | --running-time:: | 250 | --running-time:: |
| 251 | Record running and enabled time for read events (:S) | 251 | Record running and enabled time for read events (:S) |
| 252 | 252 | ||
| 253 | -k:: | ||
| 254 | --clockid:: | ||
| 255 | Sets the clock id to use for the various time fields in the perf_event_type | ||
| 256 | records. See clock_gettime(). In particular CLOCK_MONOTONIC and | ||
| 257 | CLOCK_MONOTONIC_RAW are supported, some events might also allow | ||
| 258 | CLOCK_BOOTTIME, CLOCK_REALTIME and CLOCK_TAI. | ||
| 259 | |||
| 253 | SEE ALSO | 260 | SEE ALSO |
| 254 | -------- | 261 | -------- |
| 255 | linkperf:perf-stat[1], linkperf:perf-list[1] | 262 | linkperf:perf-stat[1], linkperf:perf-list[1] |
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index ac303ef9f2f0..4ebf65c79434 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
| @@ -663,7 +663,6 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) | |||
| 663 | { | 663 | { |
| 664 | const char * const default_sort_order = "frag,hit,bytes"; | 664 | const char * const default_sort_order = "frag,hit,bytes"; |
| 665 | struct perf_data_file file = { | 665 | struct perf_data_file file = { |
| 666 | .path = input_name, | ||
| 667 | .mode = PERF_DATA_MODE_READ, | 666 | .mode = PERF_DATA_MODE_READ, |
| 668 | }; | 667 | }; |
| 669 | const struct option kmem_options[] = { | 668 | const struct option kmem_options[] = { |
| @@ -701,6 +700,8 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) | |||
| 701 | return __cmd_record(argc, argv); | 700 | return __cmd_record(argc, argv); |
| 702 | } | 701 | } |
| 703 | 702 | ||
| 703 | file.path = input_name; | ||
| 704 | |||
| 704 | session = perf_session__new(&file, false, &perf_kmem); | 705 | session = perf_session__new(&file, false, &perf_kmem); |
| 705 | if (session == NULL) | 706 | if (session == NULL) |
| 706 | return -1; | 707 | return -1; |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 18aad239b401..ac610488d2e1 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
| @@ -711,6 +711,90 @@ static int perf_record_config(const char *var, const char *value, void *cb) | |||
| 711 | return perf_default_config(var, value, cb); | 711 | return perf_default_config(var, value, cb); |
| 712 | } | 712 | } |
| 713 | 713 | ||
| 714 | struct clockid_map { | ||
| 715 | const char *name; | ||
| 716 | int clockid; | ||
| 717 | }; | ||
| 718 | |||
| 719 | #define CLOCKID_MAP(n, c) \ | ||
| 720 | { .name = n, .clockid = (c), } | ||
| 721 | |||
| 722 | #define CLOCKID_END { .name = NULL, } | ||
| 723 | |||
| 724 | |||
| 725 | /* | ||
| 726 | * Add the missing ones, we need to build on many distros... | ||
| 727 | */ | ||
| 728 | #ifndef CLOCK_MONOTONIC_RAW | ||
| 729 | #define CLOCK_MONOTONIC_RAW 4 | ||
| 730 | #endif | ||
| 731 | #ifndef CLOCK_BOOTTIME | ||
| 732 | #define CLOCK_BOOTTIME 7 | ||
| 733 | #endif | ||
| 734 | #ifndef CLOCK_TAI | ||
| 735 | #define CLOCK_TAI 11 | ||
| 736 | #endif | ||
| 737 | |||
| 738 | static const struct clockid_map clockids[] = { | ||
| 739 | /* available for all events, NMI safe */ | ||
| 740 | CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), | ||
| 741 | CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), | ||
| 742 | |||
| 743 | /* available for some events */ | ||
| 744 | CLOCKID_MAP("realtime", CLOCK_REALTIME), | ||
| 745 | CLOCKID_MAP("boottime", CLOCK_BOOTTIME), | ||
| 746 | CLOCKID_MAP("tai", CLOCK_TAI), | ||
| 747 | |||
| 748 | /* available for the lazy */ | ||
| 749 | CLOCKID_MAP("mono", CLOCK_MONOTONIC), | ||
| 750 | CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), | ||
| 751 | CLOCKID_MAP("real", CLOCK_REALTIME), | ||
| 752 | CLOCKID_MAP("boot", CLOCK_BOOTTIME), | ||
| 753 | |||
| 754 | CLOCKID_END, | ||
| 755 | }; | ||
| 756 | |||
| 757 | static int parse_clockid(const struct option *opt, const char *str, int unset) | ||
| 758 | { | ||
| 759 | struct record_opts *opts = (struct record_opts *)opt->value; | ||
| 760 | const struct clockid_map *cm; | ||
| 761 | const char *ostr = str; | ||
| 762 | |||
| 763 | if (unset) { | ||
| 764 | opts->use_clockid = 0; | ||
| 765 | return 0; | ||
| 766 | } | ||
| 767 | |||
| 768 | /* no arg passed */ | ||
| 769 | if (!str) | ||
| 770 | return 0; | ||
| 771 | |||
| 772 | /* no setting it twice */ | ||
| 773 | if (opts->use_clockid) | ||
| 774 | return -1; | ||
| 775 | |||
| 776 | opts->use_clockid = true; | ||
| 777 | |||
| 778 | /* if its a number, we're done */ | ||
| 779 | if (sscanf(str, "%d", &opts->clockid) == 1) | ||
| 780 | return 0; | ||
| 781 | |||
| 782 | /* allow a "CLOCK_" prefix to the name */ | ||
| 783 | if (!strncasecmp(str, "CLOCK_", 6)) | ||
| 784 | str += 6; | ||
| 785 | |||
| 786 | for (cm = clockids; cm->name; cm++) { | ||
| 787 | if (!strcasecmp(str, cm->name)) { | ||
| 788 | opts->clockid = cm->clockid; | ||
| 789 | return 0; | ||
| 790 | } | ||
| 791 | } | ||
| 792 | |||
| 793 | opts->use_clockid = false; | ||
| 794 | ui__warning("unknown clockid %s, check man page\n", ostr); | ||
| 795 | return -1; | ||
| 796 | } | ||
| 797 | |||
| 714 | static const char * const __record_usage[] = { | 798 | static const char * const __record_usage[] = { |
| 715 | "perf record [<options>] [<command>]", | 799 | "perf record [<options>] [<command>]", |
| 716 | "perf record [<options>] -- <command> [<options>]", | 800 | "perf record [<options>] -- <command> [<options>]", |
| @@ -842,6 +926,9 @@ struct option __record_options[] = { | |||
| 842 | "Sample machine registers on interrupt"), | 926 | "Sample machine registers on interrupt"), |
| 843 | OPT_BOOLEAN(0, "running-time", &record.opts.running_time, | 927 | OPT_BOOLEAN(0, "running-time", &record.opts.running_time, |
| 844 | "Record running/enabled time of read (:S) events"), | 928 | "Record running/enabled time of read (:S) events"), |
| 929 | OPT_CALLBACK('k', "clockid", &record.opts, | ||
| 930 | "clockid", "clockid to use for events, see clock_gettime()", | ||
| 931 | parse_clockid), | ||
| 845 | OPT_END() | 932 | OPT_END() |
| 846 | }; | 933 | }; |
| 847 | 934 | ||
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index b5b2ad4ca9c4..476cdf7afcca 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
| @@ -347,7 +347,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, | |||
| 347 | static void report__warn_kptr_restrict(const struct report *rep) | 347 | static void report__warn_kptr_restrict(const struct report *rep) |
| 348 | { | 348 | { |
| 349 | struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION]; | 349 | struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION]; |
| 350 | struct kmap *kernel_kmap = map__kmap(kernel_map); | 350 | struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL; |
| 351 | 351 | ||
| 352 | if (kernel_map == NULL || | 352 | if (kernel_map == NULL || |
| 353 | (kernel_map->dso->hit && | 353 | (kernel_map->dso->hit && |
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 3b3a5bb97059..5275bab70313 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
| @@ -23,12 +23,13 @@ | |||
| 23 | #include <semaphore.h> | 23 | #include <semaphore.h> |
| 24 | #include <pthread.h> | 24 | #include <pthread.h> |
| 25 | #include <math.h> | 25 | #include <math.h> |
| 26 | #include <api/fs/fs.h> | ||
| 26 | 27 | ||
| 27 | #define PR_SET_NAME 15 /* Set process name */ | 28 | #define PR_SET_NAME 15 /* Set process name */ |
| 28 | #define MAX_CPUS 4096 | 29 | #define MAX_CPUS 4096 |
| 29 | #define COMM_LEN 20 | 30 | #define COMM_LEN 20 |
| 30 | #define SYM_LEN 129 | 31 | #define SYM_LEN 129 |
| 31 | #define MAX_PID 65536 | 32 | #define MAX_PID 1024000 |
| 32 | 33 | ||
| 33 | struct sched_atom; | 34 | struct sched_atom; |
| 34 | 35 | ||
| @@ -124,7 +125,7 @@ struct perf_sched { | |||
| 124 | struct perf_tool tool; | 125 | struct perf_tool tool; |
| 125 | const char *sort_order; | 126 | const char *sort_order; |
| 126 | unsigned long nr_tasks; | 127 | unsigned long nr_tasks; |
| 127 | struct task_desc *pid_to_task[MAX_PID]; | 128 | struct task_desc **pid_to_task; |
| 128 | struct task_desc **tasks; | 129 | struct task_desc **tasks; |
| 129 | const struct trace_sched_handler *tp_handler; | 130 | const struct trace_sched_handler *tp_handler; |
| 130 | pthread_mutex_t start_work_mutex; | 131 | pthread_mutex_t start_work_mutex; |
| @@ -169,6 +170,7 @@ struct perf_sched { | |||
| 169 | u64 cpu_last_switched[MAX_CPUS]; | 170 | u64 cpu_last_switched[MAX_CPUS]; |
| 170 | struct rb_root atom_root, sorted_atom_root; | 171 | struct rb_root atom_root, sorted_atom_root; |
| 171 | struct list_head sort_list, cmp_pid; | 172 | struct list_head sort_list, cmp_pid; |
| 173 | bool force; | ||
| 172 | }; | 174 | }; |
| 173 | 175 | ||
| 174 | static u64 get_nsecs(void) | 176 | static u64 get_nsecs(void) |
| @@ -326,8 +328,19 @@ static struct task_desc *register_pid(struct perf_sched *sched, | |||
| 326 | unsigned long pid, const char *comm) | 328 | unsigned long pid, const char *comm) |
| 327 | { | 329 | { |
| 328 | struct task_desc *task; | 330 | struct task_desc *task; |
| 331 | static int pid_max; | ||
| 329 | 332 | ||
| 330 | BUG_ON(pid >= MAX_PID); | 333 | if (sched->pid_to_task == NULL) { |
| 334 | if (sysctl__read_int("kernel/pid_max", &pid_max) < 0) | ||
| 335 | pid_max = MAX_PID; | ||
| 336 | BUG_ON((sched->pid_to_task = calloc(pid_max, sizeof(struct task_desc *))) == NULL); | ||
| 337 | } | ||
| 338 | if (pid >= (unsigned long)pid_max) { | ||
| 339 | BUG_ON((sched->pid_to_task = realloc(sched->pid_to_task, (pid + 1) * | ||
| 340 | sizeof(struct task_desc *))) == NULL); | ||
| 341 | while (pid >= (unsigned long)pid_max) | ||
| 342 | sched->pid_to_task[pid_max++] = NULL; | ||
| 343 | } | ||
| 331 | 344 | ||
| 332 | task = sched->pid_to_task[pid]; | 345 | task = sched->pid_to_task[pid]; |
| 333 | 346 | ||
| @@ -346,7 +359,7 @@ static struct task_desc *register_pid(struct perf_sched *sched, | |||
| 346 | 359 | ||
| 347 | sched->pid_to_task[pid] = task; | 360 | sched->pid_to_task[pid] = task; |
| 348 | sched->nr_tasks++; | 361 | sched->nr_tasks++; |
| 349 | sched->tasks = realloc(sched->tasks, sched->nr_tasks * sizeof(struct task_task *)); | 362 | sched->tasks = realloc(sched->tasks, sched->nr_tasks * sizeof(struct task_desc *)); |
| 350 | BUG_ON(!sched->tasks); | 363 | BUG_ON(!sched->tasks); |
| 351 | sched->tasks[task->nr] = task; | 364 | sched->tasks[task->nr] = task; |
| 352 | 365 | ||
| @@ -425,24 +438,45 @@ static u64 get_cpu_usage_nsec_parent(void) | |||
| 425 | return sum; | 438 | return sum; |
| 426 | } | 439 | } |
| 427 | 440 | ||
| 428 | static int self_open_counters(void) | 441 | static int self_open_counters(struct perf_sched *sched, unsigned long cur_task) |
| 429 | { | 442 | { |
| 430 | struct perf_event_attr attr; | 443 | struct perf_event_attr attr; |
| 431 | char sbuf[STRERR_BUFSIZE]; | 444 | char sbuf[STRERR_BUFSIZE], info[STRERR_BUFSIZE]; |
| 432 | int fd; | 445 | int fd; |
| 446 | struct rlimit limit; | ||
| 447 | bool need_privilege = false; | ||
| 433 | 448 | ||
| 434 | memset(&attr, 0, sizeof(attr)); | 449 | memset(&attr, 0, sizeof(attr)); |
| 435 | 450 | ||
| 436 | attr.type = PERF_TYPE_SOFTWARE; | 451 | attr.type = PERF_TYPE_SOFTWARE; |
| 437 | attr.config = PERF_COUNT_SW_TASK_CLOCK; | 452 | attr.config = PERF_COUNT_SW_TASK_CLOCK; |
| 438 | 453 | ||
| 454 | force_again: | ||
| 439 | fd = sys_perf_event_open(&attr, 0, -1, -1, | 455 | fd = sys_perf_event_open(&attr, 0, -1, -1, |
| 440 | perf_event_open_cloexec_flag()); | 456 | perf_event_open_cloexec_flag()); |
| 441 | 457 | ||
| 442 | if (fd < 0) | 458 | if (fd < 0) { |
| 459 | if (errno == EMFILE) { | ||
| 460 | if (sched->force) { | ||
| 461 | BUG_ON(getrlimit(RLIMIT_NOFILE, &limit) == -1); | ||
| 462 | limit.rlim_cur += sched->nr_tasks - cur_task; | ||
| 463 | if (limit.rlim_cur > limit.rlim_max) { | ||
| 464 | limit.rlim_max = limit.rlim_cur; | ||
| 465 | need_privilege = true; | ||
| 466 | } | ||
| 467 | if (setrlimit(RLIMIT_NOFILE, &limit) == -1) { | ||
| 468 | if (need_privilege && errno == EPERM) | ||
| 469 | strcpy(info, "Need privilege\n"); | ||
| 470 | } else | ||
| 471 | goto force_again; | ||
| 472 | } else | ||
| 473 | strcpy(info, "Have a try with -f option\n"); | ||
| 474 | } | ||
| 443 | pr_err("Error: sys_perf_event_open() syscall returned " | 475 | pr_err("Error: sys_perf_event_open() syscall returned " |
| 444 | "with %d (%s)\n", fd, | 476 | "with %d (%s)\n%s", fd, |
| 445 | strerror_r(errno, sbuf, sizeof(sbuf))); | 477 | strerror_r(errno, sbuf, sizeof(sbuf)), info); |
| 478 | exit(EXIT_FAILURE); | ||
| 479 | } | ||
| 446 | return fd; | 480 | return fd; |
| 447 | } | 481 | } |
| 448 | 482 | ||
| @@ -460,6 +494,7 @@ static u64 get_cpu_usage_nsec_self(int fd) | |||
| 460 | struct sched_thread_parms { | 494 | struct sched_thread_parms { |
| 461 | struct task_desc *task; | 495 | struct task_desc *task; |
| 462 | struct perf_sched *sched; | 496 | struct perf_sched *sched; |
| 497 | int fd; | ||
| 463 | }; | 498 | }; |
| 464 | 499 | ||
| 465 | static void *thread_func(void *ctx) | 500 | static void *thread_func(void *ctx) |
| @@ -470,13 +505,12 @@ static void *thread_func(void *ctx) | |||
| 470 | u64 cpu_usage_0, cpu_usage_1; | 505 | u64 cpu_usage_0, cpu_usage_1; |
| 471 | unsigned long i, ret; | 506 | unsigned long i, ret; |
| 472 | char comm2[22]; | 507 | char comm2[22]; |
| 473 | int fd; | 508 | int fd = parms->fd; |
| 474 | 509 | ||
| 475 | zfree(&parms); | 510 | zfree(&parms); |
| 476 | 511 | ||
| 477 | sprintf(comm2, ":%s", this_task->comm); | 512 | sprintf(comm2, ":%s", this_task->comm); |
| 478 | prctl(PR_SET_NAME, comm2); | 513 | prctl(PR_SET_NAME, comm2); |
| 479 | fd = self_open_counters(); | ||
| 480 | if (fd < 0) | 514 | if (fd < 0) |
| 481 | return NULL; | 515 | return NULL; |
| 482 | again: | 516 | again: |
| @@ -528,6 +562,7 @@ static void create_tasks(struct perf_sched *sched) | |||
| 528 | BUG_ON(parms == NULL); | 562 | BUG_ON(parms == NULL); |
| 529 | parms->task = task = sched->tasks[i]; | 563 | parms->task = task = sched->tasks[i]; |
| 530 | parms->sched = sched; | 564 | parms->sched = sched; |
| 565 | parms->fd = self_open_counters(sched, i); | ||
| 531 | sem_init(&task->sleep_sem, 0, 0); | 566 | sem_init(&task->sleep_sem, 0, 0); |
| 532 | sem_init(&task->ready_for_work, 0, 0); | 567 | sem_init(&task->ready_for_work, 0, 0); |
| 533 | sem_init(&task->work_done_sem, 0, 0); | 568 | sem_init(&task->work_done_sem, 0, 0); |
| @@ -572,13 +607,13 @@ static void wait_for_tasks(struct perf_sched *sched) | |||
| 572 | cpu_usage_1 = get_cpu_usage_nsec_parent(); | 607 | cpu_usage_1 = get_cpu_usage_nsec_parent(); |
| 573 | if (!sched->runavg_cpu_usage) | 608 | if (!sched->runavg_cpu_usage) |
| 574 | sched->runavg_cpu_usage = sched->cpu_usage; | 609 | sched->runavg_cpu_usage = sched->cpu_usage; |
| 575 | sched->runavg_cpu_usage = (sched->runavg_cpu_usage * 9 + sched->cpu_usage) / 10; | 610 | sched->runavg_cpu_usage = (sched->runavg_cpu_usage * (sched->replay_repeat - 1) + sched->cpu_usage) / sched->replay_repeat; |
| 576 | 611 | ||
| 577 | sched->parent_cpu_usage = cpu_usage_1 - cpu_usage_0; | 612 | sched->parent_cpu_usage = cpu_usage_1 - cpu_usage_0; |
| 578 | if (!sched->runavg_parent_cpu_usage) | 613 | if (!sched->runavg_parent_cpu_usage) |
| 579 | sched->runavg_parent_cpu_usage = sched->parent_cpu_usage; | 614 | sched->runavg_parent_cpu_usage = sched->parent_cpu_usage; |
| 580 | sched->runavg_parent_cpu_usage = (sched->runavg_parent_cpu_usage * 9 + | 615 | sched->runavg_parent_cpu_usage = (sched->runavg_parent_cpu_usage * (sched->replay_repeat - 1) + |
| 581 | sched->parent_cpu_usage)/10; | 616 | sched->parent_cpu_usage)/sched->replay_repeat; |
| 582 | 617 | ||
| 583 | ret = pthread_mutex_lock(&sched->start_work_mutex); | 618 | ret = pthread_mutex_lock(&sched->start_work_mutex); |
| 584 | BUG_ON(ret); | 619 | BUG_ON(ret); |
| @@ -610,7 +645,7 @@ static void run_one_test(struct perf_sched *sched) | |||
| 610 | sched->sum_fluct += fluct; | 645 | sched->sum_fluct += fluct; |
| 611 | if (!sched->run_avg) | 646 | if (!sched->run_avg) |
| 612 | sched->run_avg = delta; | 647 | sched->run_avg = delta; |
| 613 | sched->run_avg = (sched->run_avg * 9 + delta) / 10; | 648 | sched->run_avg = (sched->run_avg * (sched->replay_repeat - 1) + delta) / sched->replay_repeat; |
| 614 | 649 | ||
| 615 | printf("#%-3ld: %0.3f, ", sched->nr_runs, (double)delta / 1000000.0); | 650 | printf("#%-3ld: %0.3f, ", sched->nr_runs, (double)delta / 1000000.0); |
| 616 | 651 | ||
| @@ -1452,6 +1487,7 @@ static int perf_sched__read_events(struct perf_sched *sched) | |||
| 1452 | struct perf_data_file file = { | 1487 | struct perf_data_file file = { |
| 1453 | .path = input_name, | 1488 | .path = input_name, |
| 1454 | .mode = PERF_DATA_MODE_READ, | 1489 | .mode = PERF_DATA_MODE_READ, |
| 1490 | .force = sched->force, | ||
| 1455 | }; | 1491 | }; |
| 1456 | int rc = -1; | 1492 | int rc = -1; |
| 1457 | 1493 | ||
| @@ -1685,6 +1721,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) | |||
| 1685 | "be more verbose (show symbol address, etc)"), | 1721 | "be more verbose (show symbol address, etc)"), |
| 1686 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, | 1722 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, |
| 1687 | "dump raw trace in ASCII"), | 1723 | "dump raw trace in ASCII"), |
| 1724 | OPT_BOOLEAN('f', "force", &sched.force, "don't complain, do it"), | ||
| 1688 | OPT_END() | 1725 | OPT_END() |
| 1689 | }; | 1726 | }; |
| 1690 | const struct option sched_options[] = { | 1727 | const struct option sched_options[] = { |
diff --git a/tools/perf/perf.h b/tools/perf/perf.h index c38a085a5571..e14bb637255c 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h | |||
| @@ -62,6 +62,8 @@ struct record_opts { | |||
| 62 | u64 user_interval; | 62 | u64 user_interval; |
| 63 | bool sample_transaction; | 63 | bool sample_transaction; |
| 64 | unsigned initial_delay; | 64 | unsigned initial_delay; |
| 65 | bool use_clockid; | ||
| 66 | clockid_t clockid; | ||
| 65 | }; | 67 | }; |
| 66 | 68 | ||
| 67 | struct option; | 69 | struct option; |
diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record index d3095dafed36..7e6d74946e04 100644 --- a/tools/perf/tests/attr/base-record +++ b/tools/perf/tests/attr/base-record | |||
| @@ -5,7 +5,7 @@ group_fd=-1 | |||
| 5 | flags=0|8 | 5 | flags=0|8 |
| 6 | cpu=* | 6 | cpu=* |
| 7 | type=0|1 | 7 | type=0|1 |
| 8 | size=104 | 8 | size=112 |
| 9 | config=0 | 9 | config=0 |
| 10 | sample_period=4000 | 10 | sample_period=4000 |
| 11 | sample_type=263 | 11 | sample_type=263 |
diff --git a/tools/perf/tests/attr/base-stat b/tools/perf/tests/attr/base-stat index 872ed7e24c7c..f4cf148f14cb 100644 --- a/tools/perf/tests/attr/base-stat +++ b/tools/perf/tests/attr/base-stat | |||
| @@ -5,7 +5,7 @@ group_fd=-1 | |||
| 5 | flags=0|8 | 5 | flags=0|8 |
| 6 | cpu=* | 6 | cpu=* |
| 7 | type=0 | 7 | type=0 |
| 8 | size=104 | 8 | size=112 |
| 9 | config=0 | 9 | config=0 |
| 10 | sample_period=0 | 10 | sample_period=0 |
| 11 | sample_type=0 | 11 | sample_type=0 |
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index ac243ebcb20a..3de744961739 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c | |||
| @@ -295,6 +295,36 @@ static int test__checkevent_genhw_modifier(struct perf_evlist *evlist) | |||
| 295 | return test__checkevent_genhw(evlist); | 295 | return test__checkevent_genhw(evlist); |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | static int test__checkevent_exclude_idle_modifier(struct perf_evlist *evlist) | ||
| 299 | { | ||
| 300 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
| 301 | |||
| 302 | TEST_ASSERT_VAL("wrong exclude idle", evsel->attr.exclude_idle); | ||
| 303 | TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); | ||
| 304 | TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); | ||
| 305 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
| 306 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
| 307 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); | ||
| 308 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
| 309 | |||
| 310 | return test__checkevent_symbolic_name(evlist); | ||
| 311 | } | ||
| 312 | |||
| 313 | static int test__checkevent_exclude_idle_modifier_1(struct perf_evlist *evlist) | ||
| 314 | { | ||
| 315 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
| 316 | |||
| 317 | TEST_ASSERT_VAL("wrong exclude idle", evsel->attr.exclude_idle); | ||
| 318 | TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); | ||
| 319 | TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); | ||
| 320 | TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); | ||
| 321 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
| 322 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
| 323 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
| 324 | |||
| 325 | return test__checkevent_symbolic_name(evlist); | ||
| 326 | } | ||
| 327 | |||
| 298 | static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist) | 328 | static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist) |
| 299 | { | 329 | { |
| 300 | struct perf_evsel *evsel = perf_evlist__first(evlist); | 330 | struct perf_evsel *evsel = perf_evlist__first(evlist); |
| @@ -1494,6 +1524,16 @@ static struct evlist_test test__events[] = { | |||
| 1494 | .id = 100, | 1524 | .id = 100, |
| 1495 | }, | 1525 | }, |
| 1496 | #endif | 1526 | #endif |
| 1527 | { | ||
| 1528 | .name = "instructions:I", | ||
| 1529 | .check = test__checkevent_exclude_idle_modifier, | ||
| 1530 | .id = 45, | ||
| 1531 | }, | ||
| 1532 | { | ||
| 1533 | .name = "instructions:kIG", | ||
| 1534 | .check = test__checkevent_exclude_idle_modifier_1, | ||
| 1535 | .id = 46, | ||
| 1536 | }, | ||
| 1497 | }; | 1537 | }; |
| 1498 | 1538 | ||
| 1499 | static struct evlist_test test__events_pmu[] = { | 1539 | static struct evlist_test test__events_pmu[] = { |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 82bf224bbee9..76ef7ee62640 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
| @@ -695,7 +695,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) | |||
| 695 | 695 | ||
| 696 | static bool perf_mmap__empty(struct perf_mmap *md) | 696 | static bool perf_mmap__empty(struct perf_mmap *md) |
| 697 | { | 697 | { |
| 698 | return perf_mmap__read_head(md) != md->prev; | 698 | return perf_mmap__read_head(md) == md->prev; |
| 699 | } | 699 | } |
| 700 | 700 | ||
| 701 | static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx) | 701 | static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx) |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 358e5954baa8..33e3fd8c2e68 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
| @@ -32,8 +32,12 @@ static struct { | |||
| 32 | bool exclude_guest; | 32 | bool exclude_guest; |
| 33 | bool mmap2; | 33 | bool mmap2; |
| 34 | bool cloexec; | 34 | bool cloexec; |
| 35 | bool clockid; | ||
| 36 | bool clockid_wrong; | ||
| 35 | } perf_missing_features; | 37 | } perf_missing_features; |
| 36 | 38 | ||
| 39 | static clockid_t clockid; | ||
| 40 | |||
| 37 | static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused) | 41 | static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused) |
| 38 | { | 42 | { |
| 39 | return 0; | 43 | return 0; |
| @@ -761,6 +765,12 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) | |||
| 761 | attr->disabled = 0; | 765 | attr->disabled = 0; |
| 762 | attr->enable_on_exec = 0; | 766 | attr->enable_on_exec = 0; |
| 763 | } | 767 | } |
| 768 | |||
| 769 | clockid = opts->clockid; | ||
| 770 | if (opts->use_clockid) { | ||
| 771 | attr->use_clockid = 1; | ||
| 772 | attr->clockid = opts->clockid; | ||
| 773 | } | ||
| 764 | } | 774 | } |
| 765 | 775 | ||
| 766 | static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) | 776 | static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) |
| @@ -1001,67 +1011,126 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread) | |||
| 1001 | return fd; | 1011 | return fd; |
| 1002 | } | 1012 | } |
| 1003 | 1013 | ||
| 1004 | #define __PRINT_ATTR(fmt, cast, field) \ | 1014 | struct bit_names { |
| 1005 | fprintf(fp, " %-19s "fmt"\n", #field, cast attr->field) | 1015 | int bit; |
| 1006 | 1016 | const char *name; | |
| 1007 | #define PRINT_ATTR_U32(field) __PRINT_ATTR("%u" , , field) | 1017 | }; |
| 1008 | #define PRINT_ATTR_X32(field) __PRINT_ATTR("%#x", , field) | 1018 | |
| 1009 | #define PRINT_ATTR_U64(field) __PRINT_ATTR("%" PRIu64, (uint64_t), field) | 1019 | static void __p_bits(char *buf, size_t size, u64 value, struct bit_names *bits) |
| 1010 | #define PRINT_ATTR_X64(field) __PRINT_ATTR("%#"PRIx64, (uint64_t), field) | 1020 | { |
| 1011 | 1021 | bool first_bit = true; | |
| 1012 | #define PRINT_ATTR2N(name1, field1, name2, field2) \ | 1022 | int i = 0; |
| 1013 | fprintf(fp, " %-19s %u %-19s %u\n", \ | 1023 | |
| 1014 | name1, attr->field1, name2, attr->field2) | 1024 | do { |
| 1015 | 1025 | if (value & bits[i].bit) { | |
| 1016 | #define PRINT_ATTR2(field1, field2) \ | 1026 | buf += scnprintf(buf, size, "%s%s", first_bit ? "" : "|", bits[i].name); |
| 1017 | PRINT_ATTR2N(#field1, field1, #field2, field2) | 1027 | first_bit = false; |
| 1018 | 1028 | } | |
| 1019 | static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp) | 1029 | } while (bits[++i].name != NULL); |
| 1020 | { | 1030 | } |
| 1021 | size_t ret = 0; | 1031 | |
| 1022 | 1032 | static void __p_sample_type(char *buf, size_t size, u64 value) | |
| 1023 | ret += fprintf(fp, "%.60s\n", graph_dotted_line); | 1033 | { |
| 1024 | ret += fprintf(fp, "perf_event_attr:\n"); | 1034 | #define bit_name(n) { PERF_SAMPLE_##n, #n } |
| 1025 | 1035 | struct bit_names bits[] = { | |
| 1026 | ret += PRINT_ATTR_U32(type); | 1036 | bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR), |
| 1027 | ret += PRINT_ATTR_U32(size); | 1037 | bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU), |
| 1028 | ret += PRINT_ATTR_X64(config); | 1038 | bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), |
| 1029 | ret += PRINT_ATTR_U64(sample_period); | 1039 | bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), |
| 1030 | ret += PRINT_ATTR_U64(sample_freq); | 1040 | bit_name(IDENTIFIER), bit_name(REGS_INTR), |
| 1031 | ret += PRINT_ATTR_X64(sample_type); | 1041 | { .name = NULL, } |
| 1032 | ret += PRINT_ATTR_X64(read_format); | 1042 | }; |
| 1033 | 1043 | #undef bit_name | |
| 1034 | ret += PRINT_ATTR2(disabled, inherit); | 1044 | __p_bits(buf, size, value, bits); |
| 1035 | ret += PRINT_ATTR2(pinned, exclusive); | 1045 | } |
| 1036 | ret += PRINT_ATTR2(exclude_user, exclude_kernel); | 1046 | |
| 1037 | ret += PRINT_ATTR2(exclude_hv, exclude_idle); | 1047 | static void __p_read_format(char *buf, size_t size, u64 value) |
| 1038 | ret += PRINT_ATTR2(mmap, comm); | 1048 | { |
| 1039 | ret += PRINT_ATTR2(mmap2, comm_exec); | 1049 | #define bit_name(n) { PERF_FORMAT_##n, #n } |
| 1040 | ret += PRINT_ATTR2(freq, inherit_stat); | 1050 | struct bit_names bits[] = { |
| 1041 | ret += PRINT_ATTR2(enable_on_exec, task); | 1051 | bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING), |
| 1042 | ret += PRINT_ATTR2(watermark, precise_ip); | 1052 | bit_name(ID), bit_name(GROUP), |
| 1043 | ret += PRINT_ATTR2(mmap_data, sample_id_all); | 1053 | { .name = NULL, } |
| 1044 | ret += PRINT_ATTR2(exclude_host, exclude_guest); | 1054 | }; |
| 1045 | ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel, | 1055 | #undef bit_name |
| 1046 | "excl.callchain_user", exclude_callchain_user); | 1056 | __p_bits(buf, size, value, bits); |
| 1047 | 1057 | } | |
| 1048 | ret += PRINT_ATTR_U32(wakeup_events); | 1058 | |
| 1049 | ret += PRINT_ATTR_U32(wakeup_watermark); | 1059 | #define BUF_SIZE 1024 |
| 1050 | ret += PRINT_ATTR_X32(bp_type); | 1060 | |
| 1051 | ret += PRINT_ATTR_X64(bp_addr); | 1061 | #define p_hex(val) snprintf(buf, BUF_SIZE, "%"PRIx64, (uint64_t)(val)) |
| 1052 | ret += PRINT_ATTR_X64(config1); | 1062 | #define p_unsigned(val) snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val)) |
| 1053 | ret += PRINT_ATTR_U64(bp_len); | 1063 | #define p_signed(val) snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val)) |
| 1054 | ret += PRINT_ATTR_X64(config2); | 1064 | #define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val) |
| 1055 | ret += PRINT_ATTR_X64(branch_sample_type); | 1065 | #define p_read_format(val) __p_read_format(buf, BUF_SIZE, val) |
| 1056 | ret += PRINT_ATTR_X64(sample_regs_user); | 1066 | |
| 1057 | ret += PRINT_ATTR_U32(sample_stack_user); | 1067 | #define PRINT_ATTRn(_n, _f, _p) \ |
| 1058 | ret += PRINT_ATTR_X64(sample_regs_intr); | 1068 | do { \ |
| 1059 | 1069 | if (attr->_f) { \ | |
| 1060 | ret += fprintf(fp, "%.60s\n", graph_dotted_line); | 1070 | _p(attr->_f); \ |
| 1071 | ret += attr__fprintf(fp, _n, buf, priv);\ | ||
| 1072 | } \ | ||
| 1073 | } while (0) | ||
| 1074 | |||
| 1075 | #define PRINT_ATTRf(_f, _p) PRINT_ATTRn(#_f, _f, _p) | ||
| 1076 | |||
| 1077 | int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, | ||
| 1078 | attr__fprintf_f attr__fprintf, void *priv) | ||
| 1079 | { | ||
| 1080 | char buf[BUF_SIZE]; | ||
| 1081 | int ret = 0; | ||
| 1082 | |||
| 1083 | PRINT_ATTRf(type, p_unsigned); | ||
| 1084 | PRINT_ATTRf(size, p_unsigned); | ||
| 1085 | PRINT_ATTRf(config, p_hex); | ||
| 1086 | PRINT_ATTRn("{ sample_period, sample_freq }", sample_period, p_unsigned); | ||
| 1087 | PRINT_ATTRf(sample_type, p_sample_type); | ||
| 1088 | PRINT_ATTRf(read_format, p_read_format); | ||
| 1089 | |||
| 1090 | PRINT_ATTRf(disabled, p_unsigned); | ||
| 1091 | PRINT_ATTRf(inherit, p_unsigned); | ||
| 1092 | PRINT_ATTRf(pinned, p_unsigned); | ||
| 1093 | PRINT_ATTRf(exclusive, p_unsigned); | ||
| 1094 | PRINT_ATTRf(exclude_user, p_unsigned); | ||
| 1095 | PRINT_ATTRf(exclude_kernel, p_unsigned); | ||
| 1096 | PRINT_ATTRf(exclude_hv, p_unsigned); | ||
| 1097 | PRINT_ATTRf(exclude_idle, p_unsigned); | ||
| 1098 | PRINT_ATTRf(mmap, p_unsigned); | ||
| 1099 | PRINT_ATTRf(comm, p_unsigned); | ||
| 1100 | PRINT_ATTRf(freq, p_unsigned); | ||
| 1101 | PRINT_ATTRf(inherit_stat, p_unsigned); | ||
| 1102 | PRINT_ATTRf(enable_on_exec, p_unsigned); | ||
| 1103 | PRINT_ATTRf(task, p_unsigned); | ||
| 1104 | PRINT_ATTRf(watermark, p_unsigned); | ||
| 1105 | PRINT_ATTRf(precise_ip, p_unsigned); | ||
| 1106 | PRINT_ATTRf(mmap_data, p_unsigned); | ||
| 1107 | PRINT_ATTRf(sample_id_all, p_unsigned); | ||
| 1108 | PRINT_ATTRf(exclude_host, p_unsigned); | ||
| 1109 | PRINT_ATTRf(exclude_guest, p_unsigned); | ||
| 1110 | PRINT_ATTRf(exclude_callchain_kernel, p_unsigned); | ||
| 1111 | PRINT_ATTRf(exclude_callchain_user, p_unsigned); | ||
| 1112 | PRINT_ATTRf(mmap2, p_unsigned); | ||
| 1113 | PRINT_ATTRf(comm_exec, p_unsigned); | ||
| 1114 | PRINT_ATTRf(use_clockid, p_unsigned); | ||
| 1115 | |||
| 1116 | PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned); | ||
| 1117 | PRINT_ATTRf(bp_type, p_unsigned); | ||
| 1118 | PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex); | ||
| 1119 | PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex); | ||
| 1120 | PRINT_ATTRf(sample_regs_user, p_hex); | ||
| 1121 | PRINT_ATTRf(sample_stack_user, p_unsigned); | ||
| 1122 | PRINT_ATTRf(clockid, p_signed); | ||
| 1123 | PRINT_ATTRf(sample_regs_intr, p_hex); | ||
| 1061 | 1124 | ||
| 1062 | return ret; | 1125 | return ret; |
| 1063 | } | 1126 | } |
| 1064 | 1127 | ||
| 1128 | static int __open_attr__fprintf(FILE *fp, const char *name, const char *val, | ||
| 1129 | void *priv __attribute__((unused))) | ||
| 1130 | { | ||
| 1131 | return fprintf(fp, " %-32s %s\n", name, val); | ||
| 1132 | } | ||
| 1133 | |||
| 1065 | static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | 1134 | static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, |
| 1066 | struct thread_map *threads) | 1135 | struct thread_map *threads) |
| 1067 | { | 1136 | { |
| @@ -1085,6 +1154,12 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | |||
| 1085 | } | 1154 | } |
| 1086 | 1155 | ||
| 1087 | fallback_missing_features: | 1156 | fallback_missing_features: |
| 1157 | if (perf_missing_features.clockid_wrong) | ||
| 1158 | evsel->attr.clockid = CLOCK_MONOTONIC; /* should always work */ | ||
| 1159 | if (perf_missing_features.clockid) { | ||
| 1160 | evsel->attr.use_clockid = 0; | ||
| 1161 | evsel->attr.clockid = 0; | ||
| 1162 | } | ||
| 1088 | if (perf_missing_features.cloexec) | 1163 | if (perf_missing_features.cloexec) |
| 1089 | flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC; | 1164 | flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC; |
| 1090 | if (perf_missing_features.mmap2) | 1165 | if (perf_missing_features.mmap2) |
| @@ -1095,8 +1170,12 @@ retry_sample_id: | |||
| 1095 | if (perf_missing_features.sample_id_all) | 1170 | if (perf_missing_features.sample_id_all) |
| 1096 | evsel->attr.sample_id_all = 0; | 1171 | evsel->attr.sample_id_all = 0; |
| 1097 | 1172 | ||
| 1098 | if (verbose >= 2) | 1173 | if (verbose >= 2) { |
| 1099 | perf_event_attr__fprintf(&evsel->attr, stderr); | 1174 | fprintf(stderr, "%.60s\n", graph_dotted_line); |
| 1175 | fprintf(stderr, "perf_event_attr:\n"); | ||
| 1176 | perf_event_attr__fprintf(stderr, &evsel->attr, __open_attr__fprintf, NULL); | ||
| 1177 | fprintf(stderr, "%.60s\n", graph_dotted_line); | ||
| 1178 | } | ||
| 1100 | 1179 | ||
| 1101 | for (cpu = 0; cpu < cpus->nr; cpu++) { | 1180 | for (cpu = 0; cpu < cpus->nr; cpu++) { |
| 1102 | 1181 | ||
| @@ -1122,6 +1201,17 @@ retry_open: | |||
| 1122 | goto try_fallback; | 1201 | goto try_fallback; |
| 1123 | } | 1202 | } |
| 1124 | set_rlimit = NO_CHANGE; | 1203 | set_rlimit = NO_CHANGE; |
| 1204 | |||
| 1205 | /* | ||
| 1206 | * If we succeeded but had to kill clockid, fail and | ||
| 1207 | * have perf_evsel__open_strerror() print us a nice | ||
| 1208 | * error. | ||
| 1209 | */ | ||
| 1210 | if (perf_missing_features.clockid || | ||
| 1211 | perf_missing_features.clockid_wrong) { | ||
| 1212 | err = -EINVAL; | ||
| 1213 | goto out_close; | ||
| 1214 | } | ||
| 1125 | } | 1215 | } |
| 1126 | } | 1216 | } |
| 1127 | 1217 | ||
| @@ -1155,7 +1245,17 @@ try_fallback: | |||
| 1155 | if (err != -EINVAL || cpu > 0 || thread > 0) | 1245 | if (err != -EINVAL || cpu > 0 || thread > 0) |
| 1156 | goto out_close; | 1246 | goto out_close; |
| 1157 | 1247 | ||
| 1158 | if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) { | 1248 | /* |
| 1249 | * Must probe features in the order they were added to the | ||
| 1250 | * perf_event_attr interface. | ||
| 1251 | */ | ||
| 1252 | if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) { | ||
| 1253 | perf_missing_features.clockid_wrong = true; | ||
| 1254 | goto fallback_missing_features; | ||
| 1255 | } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) { | ||
| 1256 | perf_missing_features.clockid = true; | ||
| 1257 | goto fallback_missing_features; | ||
| 1258 | } else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) { | ||
| 1159 | perf_missing_features.cloexec = true; | 1259 | perf_missing_features.cloexec = true; |
| 1160 | goto fallback_missing_features; | 1260 | goto fallback_missing_features; |
| 1161 | } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) { | 1261 | } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) { |
| @@ -1956,62 +2056,9 @@ static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...) | |||
| 1956 | return ret; | 2056 | return ret; |
| 1957 | } | 2057 | } |
| 1958 | 2058 | ||
| 1959 | static int __if_fprintf(FILE *fp, bool *first, const char *field, u64 value) | 2059 | static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, void *priv) |
| 1960 | { | ||
| 1961 | if (value == 0) | ||
| 1962 | return 0; | ||
| 1963 | |||
| 1964 | return comma_fprintf(fp, first, " %s: %" PRIu64, field, value); | ||
| 1965 | } | ||
| 1966 | |||
| 1967 | #define if_print(field) printed += __if_fprintf(fp, &first, #field, evsel->attr.field) | ||
| 1968 | |||
| 1969 | struct bit_names { | ||
| 1970 | int bit; | ||
| 1971 | const char *name; | ||
| 1972 | }; | ||
| 1973 | |||
| 1974 | static int bits__fprintf(FILE *fp, const char *field, u64 value, | ||
| 1975 | struct bit_names *bits, bool *first) | ||
| 1976 | { | ||
| 1977 | int i = 0, printed = comma_fprintf(fp, first, " %s: ", field); | ||
| 1978 | bool first_bit = true; | ||
| 1979 | |||
| 1980 | do { | ||
| 1981 | if (value & bits[i].bit) { | ||
| 1982 | printed += fprintf(fp, "%s%s", first_bit ? "" : "|", bits[i].name); | ||
| 1983 | first_bit = false; | ||
| 1984 | } | ||
| 1985 | } while (bits[++i].name != NULL); | ||
| 1986 | |||
| 1987 | return printed; | ||
| 1988 | } | ||
| 1989 | |||
| 1990 | static int sample_type__fprintf(FILE *fp, bool *first, u64 value) | ||
| 1991 | { | 2060 | { |
| 1992 | #define bit_name(n) { PERF_SAMPLE_##n, #n } | 2061 | return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val); |
| 1993 | struct bit_names bits[] = { | ||
| 1994 | bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR), | ||
| 1995 | bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU), | ||
| 1996 | bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), | ||
| 1997 | bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), | ||
| 1998 | bit_name(IDENTIFIER), bit_name(REGS_INTR), | ||
| 1999 | { .name = NULL, } | ||
| 2000 | }; | ||
| 2001 | #undef bit_name | ||
| 2002 | return bits__fprintf(fp, "sample_type", value, bits, first); | ||
| 2003 | } | ||
| 2004 | |||
| 2005 | static int read_format__fprintf(FILE *fp, bool *first, u64 value) | ||
| 2006 | { | ||
| 2007 | #define bit_name(n) { PERF_FORMAT_##n, #n } | ||
| 2008 | struct bit_names bits[] = { | ||
| 2009 | bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING), | ||
| 2010 | bit_name(ID), bit_name(GROUP), | ||
| 2011 | { .name = NULL, } | ||
| 2012 | }; | ||
| 2013 | #undef bit_name | ||
| 2014 | return bits__fprintf(fp, "read_format", value, bits, first); | ||
| 2015 | } | 2062 | } |
| 2016 | 2063 | ||
| 2017 | int perf_evsel__fprintf(struct perf_evsel *evsel, | 2064 | int perf_evsel__fprintf(struct perf_evsel *evsel, |
| @@ -2040,47 +2087,13 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, | |||
| 2040 | 2087 | ||
| 2041 | printed += fprintf(fp, "%s", perf_evsel__name(evsel)); | 2088 | printed += fprintf(fp, "%s", perf_evsel__name(evsel)); |
| 2042 | 2089 | ||
| 2043 | if (details->verbose || details->freq) { | 2090 | if (details->verbose) { |
| 2091 | printed += perf_event_attr__fprintf(fp, &evsel->attr, | ||
| 2092 | __print_attr__fprintf, &first); | ||
| 2093 | } else if (details->freq) { | ||
| 2044 | printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64, | 2094 | printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64, |
| 2045 | (u64)evsel->attr.sample_freq); | 2095 | (u64)evsel->attr.sample_freq); |
| 2046 | } | 2096 | } |
| 2047 | |||
| 2048 | if (details->verbose) { | ||
| 2049 | if_print(type); | ||
| 2050 | if_print(config); | ||
| 2051 | if_print(config1); | ||
| 2052 | if_print(config2); | ||
| 2053 | if_print(size); | ||
| 2054 | printed += sample_type__fprintf(fp, &first, evsel->attr.sample_type); | ||
| 2055 | if (evsel->attr.read_format) | ||
| 2056 | printed += read_format__fprintf(fp, &first, evsel->attr.read_format); | ||
| 2057 | if_print(disabled); | ||
| 2058 | if_print(inherit); | ||
| 2059 | if_print(pinned); | ||
| 2060 | if_print(exclusive); | ||
| 2061 | if_print(exclude_user); | ||
| 2062 | if_print(exclude_kernel); | ||
| 2063 | if_print(exclude_hv); | ||
| 2064 | if_print(exclude_idle); | ||
| 2065 | if_print(mmap); | ||
| 2066 | if_print(mmap2); | ||
| 2067 | if_print(comm); | ||
| 2068 | if_print(comm_exec); | ||
| 2069 | if_print(freq); | ||
| 2070 | if_print(inherit_stat); | ||
| 2071 | if_print(enable_on_exec); | ||
| 2072 | if_print(task); | ||
| 2073 | if_print(watermark); | ||
| 2074 | if_print(precise_ip); | ||
| 2075 | if_print(mmap_data); | ||
| 2076 | if_print(sample_id_all); | ||
| 2077 | if_print(exclude_host); | ||
| 2078 | if_print(exclude_guest); | ||
| 2079 | if_print(__reserved_1); | ||
| 2080 | if_print(wakeup_events); | ||
| 2081 | if_print(bp_type); | ||
| 2082 | if_print(branch_sample_type); | ||
| 2083 | } | ||
| 2084 | out: | 2097 | out: |
| 2085 | fputc('\n', fp); | 2098 | fputc('\n', fp); |
| 2086 | return ++printed; | 2099 | return ++printed; |
| @@ -2158,6 +2171,12 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, | |||
| 2158 | "The PMU counters are busy/taken by another profiler.\n" | 2171 | "The PMU counters are busy/taken by another profiler.\n" |
| 2159 | "We found oprofile daemon running, please stop it and try again."); | 2172 | "We found oprofile daemon running, please stop it and try again."); |
| 2160 | break; | 2173 | break; |
| 2174 | case EINVAL: | ||
| 2175 | if (perf_missing_features.clockid) | ||
| 2176 | return scnprintf(msg, size, "clockid feature not supported."); | ||
| 2177 | if (perf_missing_features.clockid_wrong) | ||
| 2178 | return scnprintf(msg, size, "wrong clockid (%d).", clockid); | ||
| 2179 | break; | ||
| 2161 | default: | 2180 | default: |
| 2162 | break; | 2181 | break; |
| 2163 | } | 2182 | } |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index c5a43d6b13dc..e486151b0308 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
| @@ -360,4 +360,10 @@ static inline bool has_branch_callstack(struct perf_evsel *evsel) | |||
| 360 | { | 360 | { |
| 361 | return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK; | 361 | return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK; |
| 362 | } | 362 | } |
| 363 | |||
| 364 | typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *); | ||
| 365 | |||
| 366 | int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, | ||
| 367 | attr__fprintf_f attr__fprintf, void *priv); | ||
| 368 | |||
| 363 | #endif /* __PERF_EVSEL_H */ | 369 | #endif /* __PERF_EVSEL_H */ |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index fb432153e2aa..fff3b2a455ae 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
| @@ -1055,6 +1055,12 @@ error: | |||
| 1055 | goto out; | 1055 | goto out; |
| 1056 | } | 1056 | } |
| 1057 | 1057 | ||
| 1058 | static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val, | ||
| 1059 | void *priv __attribute__((unused))) | ||
| 1060 | { | ||
| 1061 | return fprintf(fp, ", %s = %s", name, val); | ||
| 1062 | } | ||
| 1063 | |||
| 1058 | static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) | 1064 | static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) |
| 1059 | { | 1065 | { |
| 1060 | struct perf_evsel *evsel, *events = read_event_desc(ph, fd); | 1066 | struct perf_evsel *evsel, *events = read_event_desc(ph, fd); |
| @@ -1069,26 +1075,6 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) | |||
| 1069 | for (evsel = events; evsel->attr.size; evsel++) { | 1075 | for (evsel = events; evsel->attr.size; evsel++) { |
| 1070 | fprintf(fp, "# event : name = %s, ", evsel->name); | 1076 | fprintf(fp, "# event : name = %s, ", evsel->name); |
| 1071 | 1077 | ||
| 1072 | fprintf(fp, "type = %d, config = 0x%"PRIx64 | ||
| 1073 | ", config1 = 0x%"PRIx64", config2 = 0x%"PRIx64, | ||
| 1074 | evsel->attr.type, | ||
| 1075 | (u64)evsel->attr.config, | ||
| 1076 | (u64)evsel->attr.config1, | ||
| 1077 | (u64)evsel->attr.config2); | ||
| 1078 | |||
| 1079 | fprintf(fp, ", excl_usr = %d, excl_kern = %d", | ||
| 1080 | evsel->attr.exclude_user, | ||
| 1081 | evsel->attr.exclude_kernel); | ||
| 1082 | |||
| 1083 | fprintf(fp, ", excl_host = %d, excl_guest = %d", | ||
| 1084 | evsel->attr.exclude_host, | ||
| 1085 | evsel->attr.exclude_guest); | ||
| 1086 | |||
| 1087 | fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip); | ||
| 1088 | |||
| 1089 | fprintf(fp, ", attr_mmap2 = %d", evsel->attr.mmap2); | ||
| 1090 | fprintf(fp, ", attr_mmap = %d", evsel->attr.mmap); | ||
| 1091 | fprintf(fp, ", attr_mmap_data = %d", evsel->attr.mmap_data); | ||
| 1092 | if (evsel->ids) { | 1078 | if (evsel->ids) { |
| 1093 | fprintf(fp, ", id = {"); | 1079 | fprintf(fp, ", id = {"); |
| 1094 | for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) { | 1080 | for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) { |
| @@ -1099,6 +1085,8 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) | |||
| 1099 | fprintf(fp, " }"); | 1085 | fprintf(fp, " }"); |
| 1100 | } | 1086 | } |
| 1101 | 1087 | ||
| 1088 | perf_event_attr__fprintf(fp, &evsel->attr, __desc_attr__fprintf, NULL); | ||
| 1089 | |||
| 1102 | fputc('\n', fp); | 1090 | fputc('\n', fp); |
| 1103 | } | 1091 | } |
| 1104 | 1092 | ||
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index e45c8f33a8fd..9c380a2caa54 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
| @@ -679,6 +679,9 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) | |||
| 679 | machine->vmlinux_maps[type]->unmap_ip = | 679 | machine->vmlinux_maps[type]->unmap_ip = |
| 680 | identity__map_ip; | 680 | identity__map_ip; |
| 681 | kmap = map__kmap(machine->vmlinux_maps[type]); | 681 | kmap = map__kmap(machine->vmlinux_maps[type]); |
| 682 | if (!kmap) | ||
| 683 | return -1; | ||
| 684 | |||
| 682 | kmap->kmaps = &machine->kmaps; | 685 | kmap->kmaps = &machine->kmaps; |
| 683 | map_groups__insert(&machine->kmaps, | 686 | map_groups__insert(&machine->kmaps, |
| 684 | machine->vmlinux_maps[type]); | 687 | machine->vmlinux_maps[type]); |
| @@ -700,7 +703,7 @@ void machine__destroy_kernel_maps(struct machine *machine) | |||
| 700 | kmap = map__kmap(machine->vmlinux_maps[type]); | 703 | kmap = map__kmap(machine->vmlinux_maps[type]); |
| 701 | map_groups__remove(&machine->kmaps, | 704 | map_groups__remove(&machine->kmaps, |
| 702 | machine->vmlinux_maps[type]); | 705 | machine->vmlinux_maps[type]); |
| 703 | if (kmap->ref_reloc_sym) { | 706 | if (kmap && kmap->ref_reloc_sym) { |
| 704 | /* | 707 | /* |
| 705 | * ref_reloc_sym is shared among all maps, so free just | 708 | * ref_reloc_sym is shared among all maps, so free just |
| 706 | * on one of them. | 709 | * on one of them. |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 62ca9f2607d5..a14f08f41686 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
| @@ -778,3 +778,23 @@ struct map *maps__next(struct map *map) | |||
| 778 | return rb_entry(next, struct map, rb_node); | 778 | return rb_entry(next, struct map, rb_node); |
| 779 | return NULL; | 779 | return NULL; |
| 780 | } | 780 | } |
| 781 | |||
| 782 | struct kmap *map__kmap(struct map *map) | ||
| 783 | { | ||
| 784 | if (!map->dso || !map->dso->kernel) { | ||
| 785 | pr_err("Internal error: map__kmap with a non-kernel map\n"); | ||
| 786 | return NULL; | ||
| 787 | } | ||
| 788 | return (struct kmap *)(map + 1); | ||
| 789 | } | ||
| 790 | |||
| 791 | struct map_groups *map__kmaps(struct map *map) | ||
| 792 | { | ||
| 793 | struct kmap *kmap = map__kmap(map); | ||
| 794 | |||
| 795 | if (!kmap || !kmap->kmaps) { | ||
| 796 | pr_err("Internal error: map__kmaps with a non-kernel map\n"); | ||
| 797 | return NULL; | ||
| 798 | } | ||
| 799 | return kmap->kmaps; | ||
| 800 | } | ||
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 0e42438b1e59..ec19c59ca38e 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
| @@ -76,10 +76,8 @@ static inline struct map_groups *map_groups__get(struct map_groups *mg) | |||
| 76 | 76 | ||
| 77 | void map_groups__put(struct map_groups *mg); | 77 | void map_groups__put(struct map_groups *mg); |
| 78 | 78 | ||
| 79 | static inline struct kmap *map__kmap(struct map *map) | 79 | struct kmap *map__kmap(struct map *map); |
| 80 | { | 80 | struct map_groups *map__kmaps(struct map *map); |
| 81 | return (struct kmap *)(map + 1); | ||
| 82 | } | ||
| 83 | 81 | ||
| 84 | static inline u64 map__map_ip(struct map *map, u64 ip) | 82 | static inline u64 map__map_ip(struct map *map, u64 ip) |
| 85 | { | 83 | { |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index fe07573d5ed4..be0655388b38 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
| @@ -709,6 +709,7 @@ struct event_modifier { | |||
| 709 | int eh; | 709 | int eh; |
| 710 | int eH; | 710 | int eH; |
| 711 | int eG; | 711 | int eG; |
| 712 | int eI; | ||
| 712 | int precise; | 713 | int precise; |
| 713 | int exclude_GH; | 714 | int exclude_GH; |
| 714 | int sample_read; | 715 | int sample_read; |
| @@ -723,6 +724,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str, | |||
| 723 | int eh = evsel ? evsel->attr.exclude_hv : 0; | 724 | int eh = evsel ? evsel->attr.exclude_hv : 0; |
| 724 | int eH = evsel ? evsel->attr.exclude_host : 0; | 725 | int eH = evsel ? evsel->attr.exclude_host : 0; |
| 725 | int eG = evsel ? evsel->attr.exclude_guest : 0; | 726 | int eG = evsel ? evsel->attr.exclude_guest : 0; |
| 727 | int eI = evsel ? evsel->attr.exclude_idle : 0; | ||
| 726 | int precise = evsel ? evsel->attr.precise_ip : 0; | 728 | int precise = evsel ? evsel->attr.precise_ip : 0; |
| 727 | int sample_read = 0; | 729 | int sample_read = 0; |
| 728 | int pinned = evsel ? evsel->attr.pinned : 0; | 730 | int pinned = evsel ? evsel->attr.pinned : 0; |
| @@ -753,6 +755,8 @@ static int get_event_modifier(struct event_modifier *mod, char *str, | |||
| 753 | if (!exclude_GH) | 755 | if (!exclude_GH) |
| 754 | exclude_GH = eG = eH = 1; | 756 | exclude_GH = eG = eH = 1; |
| 755 | eH = 0; | 757 | eH = 0; |
| 758 | } else if (*str == 'I') { | ||
| 759 | eI = 1; | ||
| 756 | } else if (*str == 'p') { | 760 | } else if (*str == 'p') { |
| 757 | precise++; | 761 | precise++; |
| 758 | /* use of precise requires exclude_guest */ | 762 | /* use of precise requires exclude_guest */ |
| @@ -786,6 +790,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str, | |||
| 786 | mod->eh = eh; | 790 | mod->eh = eh; |
| 787 | mod->eH = eH; | 791 | mod->eH = eH; |
| 788 | mod->eG = eG; | 792 | mod->eG = eG; |
| 793 | mod->eI = eI; | ||
| 789 | mod->precise = precise; | 794 | mod->precise = precise; |
| 790 | mod->exclude_GH = exclude_GH; | 795 | mod->exclude_GH = exclude_GH; |
| 791 | mod->sample_read = sample_read; | 796 | mod->sample_read = sample_read; |
| @@ -803,7 +808,7 @@ static int check_modifier(char *str) | |||
| 803 | char *p = str; | 808 | char *p = str; |
| 804 | 809 | ||
| 805 | /* The sizeof includes 0 byte as well. */ | 810 | /* The sizeof includes 0 byte as well. */ |
| 806 | if (strlen(str) > (sizeof("ukhGHpppSD") - 1)) | 811 | if (strlen(str) > (sizeof("ukhGHpppSDI") - 1)) |
| 807 | return -1; | 812 | return -1; |
| 808 | 813 | ||
| 809 | while (*p) { | 814 | while (*p) { |
| @@ -839,6 +844,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add) | |||
| 839 | evsel->attr.precise_ip = mod.precise; | 844 | evsel->attr.precise_ip = mod.precise; |
| 840 | evsel->attr.exclude_host = mod.eH; | 845 | evsel->attr.exclude_host = mod.eH; |
| 841 | evsel->attr.exclude_guest = mod.eG; | 846 | evsel->attr.exclude_guest = mod.eG; |
| 847 | evsel->attr.exclude_idle = mod.eI; | ||
| 842 | evsel->exclude_GH = mod.exclude_GH; | 848 | evsel->exclude_GH = mod.exclude_GH; |
| 843 | evsel->sample_read = mod.sample_read; | 849 | evsel->sample_read = mod.sample_read; |
| 844 | 850 | ||
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 94eacb6c1ef7..8895cf3132ab 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l | |||
| @@ -101,7 +101,7 @@ num_raw_hex [a-fA-F0-9]+ | |||
| 101 | name [a-zA-Z_*?][a-zA-Z0-9_*?]* | 101 | name [a-zA-Z_*?][a-zA-Z0-9_*?]* |
| 102 | name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]* | 102 | name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]* |
| 103 | /* If you add a modifier you need to update check_modifier() */ | 103 | /* If you add a modifier you need to update check_modifier() */ |
| 104 | modifier_event [ukhpGHSD]+ | 104 | modifier_event [ukhpGHSDI]+ |
| 105 | modifier_bp [rwx]{1,3} | 105 | modifier_bp [rwx]{1,3} |
| 106 | 106 | ||
| 107 | %% | 107 | %% |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 8feac0774c41..b78851732a71 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
| @@ -135,6 +135,8 @@ static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void) | |||
| 135 | return NULL; | 135 | return NULL; |
| 136 | 136 | ||
| 137 | kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]); | 137 | kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]); |
| 138 | if (!kmap) | ||
| 139 | return NULL; | ||
| 138 | return kmap->ref_reloc_sym; | 140 | return kmap->ref_reloc_sym; |
| 139 | } | 141 | } |
| 140 | 142 | ||
| @@ -320,7 +322,8 @@ static int find_alternative_probe_point(struct debuginfo *dinfo, | |||
| 320 | ret = -ENOENT; | 322 | ret = -ENOENT; |
| 321 | goto out; | 323 | goto out; |
| 322 | } | 324 | } |
| 323 | pr_debug("Symbol %s address found : %lx\n", pp->function, address); | 325 | pr_debug("Symbol %s address found : %" PRIx64 "\n", |
| 326 | pp->function, address); | ||
| 324 | 327 | ||
| 325 | ret = debuginfo__find_probe_point(dinfo, (unsigned long)address, | 328 | ret = debuginfo__find_probe_point(dinfo, (unsigned long)address, |
| 326 | result); | 329 | result); |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index dfacf1d50162..0c74012575ac 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
| @@ -1466,6 +1466,9 @@ int maps__set_kallsyms_ref_reloc_sym(struct map **maps, | |||
| 1466 | 1466 | ||
| 1467 | for (i = 0; i < MAP__NR_TYPES; ++i) { | 1467 | for (i = 0; i < MAP__NR_TYPES; ++i) { |
| 1468 | struct kmap *kmap = map__kmap(maps[i]); | 1468 | struct kmap *kmap = map__kmap(maps[i]); |
| 1469 | |||
| 1470 | if (!kmap) | ||
| 1471 | continue; | ||
| 1469 | kmap->ref_reloc_sym = ref; | 1472 | kmap->ref_reloc_sym = ref; |
| 1470 | } | 1473 | } |
| 1471 | 1474 | ||
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 476268c99431..a7ab6063e038 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
| @@ -776,6 +776,7 @@ int dso__load_sym(struct dso *dso, struct map *map, | |||
| 776 | symbol_filter_t filter, int kmodule) | 776 | symbol_filter_t filter, int kmodule) |
| 777 | { | 777 | { |
| 778 | struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; | 778 | struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; |
| 779 | struct map_groups *kmaps = kmap ? map__kmaps(map) : NULL; | ||
| 779 | struct map *curr_map = map; | 780 | struct map *curr_map = map; |
| 780 | struct dso *curr_dso = dso; | 781 | struct dso *curr_dso = dso; |
| 781 | Elf_Data *symstrs, *secstrs; | 782 | Elf_Data *symstrs, *secstrs; |
| @@ -791,6 +792,9 @@ int dso__load_sym(struct dso *dso, struct map *map, | |||
| 791 | int nr = 0; | 792 | int nr = 0; |
| 792 | bool remap_kernel = false, adjust_kernel_syms = false; | 793 | bool remap_kernel = false, adjust_kernel_syms = false; |
| 793 | 794 | ||
| 795 | if (kmap && !kmaps) | ||
| 796 | return -1; | ||
| 797 | |||
| 794 | dso->symtab_type = syms_ss->type; | 798 | dso->symtab_type = syms_ss->type; |
| 795 | dso->is_64_bit = syms_ss->is_64_bit; | 799 | dso->is_64_bit = syms_ss->is_64_bit; |
| 796 | dso->rel = syms_ss->ehdr.e_type == ET_REL; | 800 | dso->rel = syms_ss->ehdr.e_type == ET_REL; |
| @@ -958,8 +962,10 @@ int dso__load_sym(struct dso *dso, struct map *map, | |||
| 958 | map->map_ip = map__map_ip; | 962 | map->map_ip = map__map_ip; |
| 959 | map->unmap_ip = map__unmap_ip; | 963 | map->unmap_ip = map__unmap_ip; |
| 960 | /* Ensure maps are correctly ordered */ | 964 | /* Ensure maps are correctly ordered */ |
| 961 | map_groups__remove(kmap->kmaps, map); | 965 | if (kmaps) { |
| 962 | map_groups__insert(kmap->kmaps, map); | 966 | map_groups__remove(kmaps, map); |
| 967 | map_groups__insert(kmaps, map); | ||
| 968 | } | ||
| 963 | } | 969 | } |
| 964 | 970 | ||
| 965 | /* | 971 | /* |
| @@ -983,7 +989,7 @@ int dso__load_sym(struct dso *dso, struct map *map, | |||
| 983 | snprintf(dso_name, sizeof(dso_name), | 989 | snprintf(dso_name, sizeof(dso_name), |
| 984 | "%s%s", dso->short_name, section_name); | 990 | "%s%s", dso->short_name, section_name); |
| 985 | 991 | ||
| 986 | curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name); | 992 | curr_map = map_groups__find_by_name(kmaps, map->type, dso_name); |
| 987 | if (curr_map == NULL) { | 993 | if (curr_map == NULL) { |
| 988 | u64 start = sym.st_value; | 994 | u64 start = sym.st_value; |
| 989 | 995 | ||
| @@ -1013,7 +1019,7 @@ int dso__load_sym(struct dso *dso, struct map *map, | |||
| 1013 | curr_map->unmap_ip = identity__map_ip; | 1019 | curr_map->unmap_ip = identity__map_ip; |
| 1014 | } | 1020 | } |
| 1015 | curr_dso->symtab_type = dso->symtab_type; | 1021 | curr_dso->symtab_type = dso->symtab_type; |
| 1016 | map_groups__insert(kmap->kmaps, curr_map); | 1022 | map_groups__insert(kmaps, curr_map); |
| 1017 | /* | 1023 | /* |
| 1018 | * The new DSO should go to the kernel DSOS | 1024 | * The new DSO should go to the kernel DSOS |
| 1019 | */ | 1025 | */ |
| @@ -1075,7 +1081,7 @@ new_symbol: | |||
| 1075 | * We need to fixup this here too because we create new | 1081 | * We need to fixup this here too because we create new |
| 1076 | * maps here, for things like vsyscall sections. | 1082 | * maps here, for things like vsyscall sections. |
| 1077 | */ | 1083 | */ |
| 1078 | __map_groups__fixup_end(kmap->kmaps, map->type); | 1084 | __map_groups__fixup_end(kmaps, map->type); |
| 1079 | } | 1085 | } |
| 1080 | } | 1086 | } |
| 1081 | err = nr; | 1087 | err = nr; |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index fddeb9073039..201f6c4ca738 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
| @@ -630,13 +630,16 @@ static int dso__load_all_kallsyms(struct dso *dso, const char *filename, | |||
| 630 | static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, | 630 | static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, |
| 631 | symbol_filter_t filter) | 631 | symbol_filter_t filter) |
| 632 | { | 632 | { |
| 633 | struct map_groups *kmaps = map__kmap(map)->kmaps; | 633 | struct map_groups *kmaps = map__kmaps(map); |
| 634 | struct map *curr_map; | 634 | struct map *curr_map; |
| 635 | struct symbol *pos; | 635 | struct symbol *pos; |
| 636 | int count = 0, moved = 0; | 636 | int count = 0, moved = 0; |
| 637 | struct rb_root *root = &dso->symbols[map->type]; | 637 | struct rb_root *root = &dso->symbols[map->type]; |
| 638 | struct rb_node *next = rb_first(root); | 638 | struct rb_node *next = rb_first(root); |
| 639 | 639 | ||
| 640 | if (!kmaps) | ||
| 641 | return -1; | ||
| 642 | |||
| 640 | while (next) { | 643 | while (next) { |
| 641 | char *module; | 644 | char *module; |
| 642 | 645 | ||
| @@ -682,8 +685,8 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, | |||
| 682 | static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta, | 685 | static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta, |
| 683 | symbol_filter_t filter) | 686 | symbol_filter_t filter) |
| 684 | { | 687 | { |
| 685 | struct map_groups *kmaps = map__kmap(map)->kmaps; | 688 | struct map_groups *kmaps = map__kmaps(map); |
| 686 | struct machine *machine = kmaps->machine; | 689 | struct machine *machine; |
| 687 | struct map *curr_map = map; | 690 | struct map *curr_map = map; |
| 688 | struct symbol *pos; | 691 | struct symbol *pos; |
| 689 | int count = 0, moved = 0; | 692 | int count = 0, moved = 0; |
| @@ -691,6 +694,11 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta, | |||
| 691 | struct rb_node *next = rb_first(root); | 694 | struct rb_node *next = rb_first(root); |
| 692 | int kernel_range = 0; | 695 | int kernel_range = 0; |
| 693 | 696 | ||
| 697 | if (!kmaps) | ||
| 698 | return -1; | ||
| 699 | |||
| 700 | machine = kmaps->machine; | ||
| 701 | |||
| 694 | while (next) { | 702 | while (next) { |
| 695 | char *module; | 703 | char *module; |
| 696 | 704 | ||
| @@ -1025,9 +1033,12 @@ static bool filename_from_kallsyms_filename(char *filename, | |||
| 1025 | static int validate_kcore_modules(const char *kallsyms_filename, | 1033 | static int validate_kcore_modules(const char *kallsyms_filename, |
| 1026 | struct map *map) | 1034 | struct map *map) |
| 1027 | { | 1035 | { |
| 1028 | struct map_groups *kmaps = map__kmap(map)->kmaps; | 1036 | struct map_groups *kmaps = map__kmaps(map); |
| 1029 | char modules_filename[PATH_MAX]; | 1037 | char modules_filename[PATH_MAX]; |
| 1030 | 1038 | ||
| 1039 | if (!kmaps) | ||
| 1040 | return -EINVAL; | ||
| 1041 | |||
| 1031 | if (!filename_from_kallsyms_filename(modules_filename, "modules", | 1042 | if (!filename_from_kallsyms_filename(modules_filename, "modules", |
| 1032 | kallsyms_filename)) | 1043 | kallsyms_filename)) |
| 1033 | return -EINVAL; | 1044 | return -EINVAL; |
| @@ -1043,6 +1054,9 @@ static int validate_kcore_addresses(const char *kallsyms_filename, | |||
| 1043 | { | 1054 | { |
| 1044 | struct kmap *kmap = map__kmap(map); | 1055 | struct kmap *kmap = map__kmap(map); |
| 1045 | 1056 | ||
| 1057 | if (!kmap) | ||
| 1058 | return -EINVAL; | ||
| 1059 | |||
| 1046 | if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) { | 1060 | if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) { |
| 1047 | u64 start; | 1061 | u64 start; |
| 1048 | 1062 | ||
| @@ -1081,8 +1095,8 @@ static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data) | |||
| 1081 | static int dso__load_kcore(struct dso *dso, struct map *map, | 1095 | static int dso__load_kcore(struct dso *dso, struct map *map, |
| 1082 | const char *kallsyms_filename) | 1096 | const char *kallsyms_filename) |
| 1083 | { | 1097 | { |
| 1084 | struct map_groups *kmaps = map__kmap(map)->kmaps; | 1098 | struct map_groups *kmaps = map__kmaps(map); |
| 1085 | struct machine *machine = kmaps->machine; | 1099 | struct machine *machine; |
| 1086 | struct kcore_mapfn_data md; | 1100 | struct kcore_mapfn_data md; |
| 1087 | struct map *old_map, *new_map, *replacement_map = NULL; | 1101 | struct map *old_map, *new_map, *replacement_map = NULL; |
| 1088 | bool is_64_bit; | 1102 | bool is_64_bit; |
| @@ -1090,6 +1104,11 @@ static int dso__load_kcore(struct dso *dso, struct map *map, | |||
| 1090 | char kcore_filename[PATH_MAX]; | 1104 | char kcore_filename[PATH_MAX]; |
| 1091 | struct symbol *sym; | 1105 | struct symbol *sym; |
| 1092 | 1106 | ||
| 1107 | if (!kmaps) | ||
| 1108 | return -EINVAL; | ||
| 1109 | |||
| 1110 | machine = kmaps->machine; | ||
| 1111 | |||
| 1093 | /* This function requires that the map is the kernel map */ | 1112 | /* This function requires that the map is the kernel map */ |
| 1094 | if (map != machine->vmlinux_maps[map->type]) | 1113 | if (map != machine->vmlinux_maps[map->type]) |
| 1095 | return -EINVAL; | 1114 | return -EINVAL; |
| @@ -1202,6 +1221,9 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta) | |||
| 1202 | struct kmap *kmap = map__kmap(map); | 1221 | struct kmap *kmap = map__kmap(map); |
| 1203 | u64 addr; | 1222 | u64 addr; |
| 1204 | 1223 | ||
| 1224 | if (!kmap) | ||
| 1225 | return -1; | ||
| 1226 | |||
| 1205 | if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name) | 1227 | if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name) |
| 1206 | return 0; | 1228 | return 0; |
| 1207 | 1229 | ||
