aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-04-08 11:03:47 -0400
committerIngo Molnar <mingo@kernel.org>2015-04-08 11:03:47 -0400
commit51ab7155c08baf45cc2aa911961e5b78422e478f (patch)
treef6b0c0d524a376fa4e0411d08bac307d931f35c9 /tools/perf
parent6645f3187f5beb64f7a40515cfa18f3889264ece (diff)
parenta1e12da4796a4ddd0e911687a290eb396d1c64bf (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: User visible changes: - Teach 'perf record' about perf_event_attr.clockid (Peter Zijlstra) - Improve 'perf sched replay' on high CPU core count machines (Yunlong Song) - Consider PERF_RECORD_ events with cpumode == 0 in 'perf top', removing one cause of long term memory usage buildup, i.e. not processing PERF_RECORD_EXIT events (Arnaldo Carvalho de Melo) - Add 'I' event modifier for perf_event_attr.exclude_idle bit (Jiri Olsa) - Respect -i option 'in perf kmem' (Jiri Olsa) Infrastructure changes: - Honor operator priority in libtraceevent (Namhyung Kim) - Merge all perf_event_attr print functions (Peter Zijlstra) - Check kmaps access to make code more robust (Wang Nan) - Fix inverted logic in perf_mmap__empty() (He Kuang) - Fix ARM 32 'perf probe' building error (Wang Nan) - Fix perf_event_attr tests (Jiri Olsa) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-list.txt1
-rw-r--r--tools/perf/Documentation/perf-record.txt7
-rw-r--r--tools/perf/builtin-kmem.c3
-rw-r--r--tools/perf/builtin-record.c87
-rw-r--r--tools/perf/builtin-report.c2
-rw-r--r--tools/perf/builtin-sched.c67
-rw-r--r--tools/perf/perf.h2
-rw-r--r--tools/perf/tests/attr/base-record2
-rw-r--r--tools/perf/tests/attr/base-stat2
-rw-r--r--tools/perf/tests/parse-events.c40
-rw-r--r--tools/perf/util/evlist.c2
-rw-r--r--tools/perf/util/evsel.c325
-rw-r--r--tools/perf/util/evsel.h6
-rw-r--r--tools/perf/util/header.c28
-rw-r--r--tools/perf/util/machine.c5
-rw-r--r--tools/perf/util/map.c20
-rw-r--r--tools/perf/util/map.h6
-rw-r--r--tools/perf/util/parse-events.c8
-rw-r--r--tools/perf/util/parse-events.l2
-rw-r--r--tools/perf/util/probe-event.c5
-rw-r--r--tools/perf/util/session.c3
-rw-r--r--tools/perf/util/symbol-elf.c16
-rw-r--r--tools/perf/util/symbol.c34
23 files changed, 461 insertions, 212 deletions
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::
251Record running and enabled time for read events (:S) 251Record running and enabled time for read events (:S)
252 252
253-k::
254--clockid::
255Sets the clock id to use for the various time fields in the perf_event_type
256records. See clock_gettime(). In particular CLOCK_MONOTONIC and
257CLOCK_MONOTONIC_RAW are supported, some events might also allow
258CLOCK_BOOTTIME, CLOCK_REALTIME and CLOCK_TAI.
259
253SEE ALSO 260SEE ALSO
254-------- 261--------
255linkperf:perf-stat[1], linkperf:perf-list[1] 262linkperf: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
714struct 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
738static 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
757static 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
714static const char * const __record_usage[] = { 798static 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,
347static void report__warn_kptr_restrict(const struct report *rep) 347static 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
33struct sched_atom; 34struct 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
174static u64 get_nsecs(void) 176static 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
428static int self_open_counters(void) 441static 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
454force_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)
460struct sched_thread_parms { 494struct 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
465static void *thread_func(void *ctx) 500static 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;
482again: 516again:
@@ -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
67struct option; 69struct 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
5flags=0|8 5flags=0|8
6cpu=* 6cpu=*
7type=0|1 7type=0|1
8size=104 8size=112
9config=0 9config=0
10sample_period=4000 10sample_period=4000
11sample_type=263 11sample_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
5flags=0|8 5flags=0|8
6cpu=* 6cpu=*
7type=0 7type=0
8size=104 8size=112
9config=0 9config=0
10sample_period=0 10sample_period=0
11sample_type=0 11sample_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
298static 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
313static 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
298static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist) 328static 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
1499static struct evlist_test test__events_pmu[] = { 1539static 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
696static bool perf_mmap__empty(struct perf_mmap *md) 696static 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
701static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx) 701static 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
39static clockid_t clockid;
40
37static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused) 41static 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
766static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 776static 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) \ 1014struct 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) 1019static 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 }
1019static 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 1032static 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); 1047static 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); 1068do { \
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
1077int 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
1128static 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
1065static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 1134static 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
1087fallback_missing_features: 1156fallback_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
1959static int __if_fprintf(FILE *fp, bool *first, const char *field, u64 value) 2059static 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
1969struct bit_names {
1970 int bit;
1971 const char *name;
1972};
1973
1974static 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
1990static 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
2005static 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
2017int perf_evsel__fprintf(struct perf_evsel *evsel, 2064int 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 }
2084out: 2097out:
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
364typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *);
365
366int 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
1058static 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
1058static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) 1064static 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
782struct 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
791struct 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
77void map_groups__put(struct map_groups *mg); 77void map_groups__put(struct map_groups *mg);
78 78
79static inline struct kmap *map__kmap(struct map *map) 79struct kmap *map__kmap(struct map *map);
80{ 80struct map_groups *map__kmaps(struct map *map);
81 return (struct kmap *)(map + 1);
82}
83 81
84static inline u64 map__map_ip(struct map *map, u64 ip) 82static 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]+
101name [a-zA-Z_*?][a-zA-Z0-9_*?]* 101name [a-zA-Z_*?][a-zA-Z0-9_*?]*
102name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]* 102name_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() */
104modifier_event [ukhpGHSD]+ 104modifier_event [ukhpGHSDI]+
105modifier_bp [rwx]{1,3} 105modifier_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,
630static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, 630static 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,
682static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta, 685static 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,
1025static int validate_kcore_modules(const char *kallsyms_filename, 1033static 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)
1081static int dso__load_kcore(struct dso *dso, struct map *map, 1095static 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