diff options
author | Cody P Schafer <cody@linux.vnet.ibm.com> | 2015-01-07 20:13:50 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-01-21 11:24:32 -0500 |
commit | 688d4dfcdd624192cbf03c08402e444d1d11f294 (patch) | |
tree | a1db7d5240caa8c77a6ba53738aff669cd5b4e91 | |
parent | c8defe249460b6fa3103797273f590372cc62efc (diff) |
perf tools: Support parsing parameterized events
Enable event specification like:
pmu/event_name,param1=0x1,param2=0x4/
Assuming that
/sys/bus/event_source/devices/pmu/events/event_name
Contains something like
param2=?,bar=1,param1=?
Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Cody P Schafer <dev@codyps.com>
Cc: Haren Myneni <hbabu@us.ibm.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: linuxppc-dev@lists.ozlabs.org
Link: http://lkml.kernel.org/r/1420679633-28856-2-git-send-email-sukadev@linux.vnet.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/util/parse-events.h | 1 | ||||
-rw-r--r-- | tools/perf/util/pmu.c | 74 |
2 files changed, 64 insertions, 11 deletions
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index db2cf78ff0f3..ca226cef8460 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h | |||
@@ -71,6 +71,7 @@ struct parse_events_term { | |||
71 | int type_val; | 71 | int type_val; |
72 | int type_term; | 72 | int type_term; |
73 | struct list_head list; | 73 | struct list_head list; |
74 | bool used; | ||
74 | }; | 75 | }; |
75 | 76 | ||
76 | struct parse_events_evlist { | 77 | struct parse_events_evlist { |
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 5c9c4947cfb4..bfbecf7abd38 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c | |||
@@ -551,31 +551,68 @@ static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, | |||
551 | } | 551 | } |
552 | 552 | ||
553 | /* | 553 | /* |
554 | * Term is a string term, and might be a param-term. Try to look up it's value | ||
555 | * in the remaining terms. | ||
556 | * - We have a term like "base-or-format-term=param-term", | ||
557 | * - We need to find the value supplied for "param-term" (with param-term named | ||
558 | * in a config string) later on in the term list. | ||
559 | */ | ||
560 | static int pmu_resolve_param_term(struct parse_events_term *term, | ||
561 | struct list_head *head_terms, | ||
562 | __u64 *value) | ||
563 | { | ||
564 | struct parse_events_term *t; | ||
565 | |||
566 | list_for_each_entry(t, head_terms, list) { | ||
567 | if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { | ||
568 | if (!strcmp(t->config, term->config)) { | ||
569 | t->used = true; | ||
570 | *value = t->val.num; | ||
571 | return 0; | ||
572 | } | ||
573 | } | ||
574 | } | ||
575 | |||
576 | if (verbose) | ||
577 | printf("Required parameter '%s' not specified\n", term->config); | ||
578 | |||
579 | return -1; | ||
580 | } | ||
581 | |||
582 | /* | ||
554 | * Setup one of config[12] attr members based on the | 583 | * Setup one of config[12] attr members based on the |
555 | * user input data - term parameter. | 584 | * user input data - term parameter. |
556 | */ | 585 | */ |
557 | static int pmu_config_term(struct list_head *formats, | 586 | static int pmu_config_term(struct list_head *formats, |
558 | struct perf_event_attr *attr, | 587 | struct perf_event_attr *attr, |
559 | struct parse_events_term *term, | 588 | struct parse_events_term *term, |
589 | struct list_head *head_terms, | ||
560 | bool zero) | 590 | bool zero) |
561 | { | 591 | { |
562 | struct perf_pmu_format *format; | 592 | struct perf_pmu_format *format; |
563 | __u64 *vp; | 593 | __u64 *vp; |
594 | __u64 val; | ||
595 | |||
596 | /* | ||
597 | * If this is a parameter we've already used for parameterized-eval, | ||
598 | * skip it in normal eval. | ||
599 | */ | ||
600 | if (term->used) | ||
601 | return 0; | ||
564 | 602 | ||
565 | /* | 603 | /* |
566 | * Support only for hardcoded and numnerial terms. | ||
567 | * Hardcoded terms should be already in, so nothing | 604 | * Hardcoded terms should be already in, so nothing |
568 | * to be done for them. | 605 | * to be done for them. |
569 | */ | 606 | */ |
570 | if (parse_events__is_hardcoded_term(term)) | 607 | if (parse_events__is_hardcoded_term(term)) |
571 | return 0; | 608 | return 0; |
572 | 609 | ||
573 | if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM) | ||
574 | return -EINVAL; | ||
575 | |||
576 | format = pmu_find_format(formats, term->config); | 610 | format = pmu_find_format(formats, term->config); |
577 | if (!format) | 611 | if (!format) { |
612 | if (verbose) | ||
613 | printf("Invalid event/parameter '%s'\n", term->config); | ||
578 | return -EINVAL; | 614 | return -EINVAL; |
615 | } | ||
579 | 616 | ||
580 | switch (format->value) { | 617 | switch (format->value) { |
581 | case PERF_PMU_FORMAT_VALUE_CONFIG: | 618 | case PERF_PMU_FORMAT_VALUE_CONFIG: |
@@ -592,11 +629,25 @@ static int pmu_config_term(struct list_head *formats, | |||
592 | } | 629 | } |
593 | 630 | ||
594 | /* | 631 | /* |
595 | * XXX If we ever decide to go with string values for | 632 | * Either directly use a numeric term, or try to translate string terms |
596 | * non-hardcoded terms, here's the place to translate | 633 | * using event parameters. |
597 | * them into value. | ||
598 | */ | 634 | */ |
599 | pmu_format_value(format->bits, term->val.num, vp, zero); | 635 | if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) |
636 | val = term->val.num; | ||
637 | else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { | ||
638 | if (strcmp(term->val.str, "?")) { | ||
639 | if (verbose) | ||
640 | pr_info("Invalid sysfs entry %s=%s\n", | ||
641 | term->config, term->val.str); | ||
642 | return -EINVAL; | ||
643 | } | ||
644 | |||
645 | if (pmu_resolve_param_term(term, head_terms, &val)) | ||
646 | return -EINVAL; | ||
647 | } else | ||
648 | return -EINVAL; | ||
649 | |||
650 | pmu_format_value(format->bits, val, vp, zero); | ||
600 | return 0; | 651 | return 0; |
601 | } | 652 | } |
602 | 653 | ||
@@ -607,9 +658,10 @@ int perf_pmu__config_terms(struct list_head *formats, | |||
607 | { | 658 | { |
608 | struct parse_events_term *term; | 659 | struct parse_events_term *term; |
609 | 660 | ||
610 | list_for_each_entry(term, head_terms, list) | 661 | list_for_each_entry(term, head_terms, list) { |
611 | if (pmu_config_term(formats, attr, term, zero)) | 662 | if (pmu_config_term(formats, attr, term, head_terms, zero)) |
612 | return -EINVAL; | 663 | return -EINVAL; |
664 | } | ||
613 | 665 | ||
614 | return 0; | 666 | return 0; |
615 | } | 667 | } |