aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorMathieu Poirier <mathieu.poirier@linaro.org>2016-09-06 12:37:15 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-09-13 16:09:11 -0400
commitdd60fba7324572498d91163e96b1cfe5cd5f7f3b (patch)
tree840943df1c2f561e7de3c4a0e603f58e82b25e1a /tools/perf
parent30d476ae738d1ce33f170dd79398ecd211274df6 (diff)
perf tools: Add infrastructure for PMU specific configuration
This patch adds PMU driver specific configuration to the parser infrastructure by preceding any term with the '@' letter. As such doing something like: perf record -e some_event/@cfg1,@cfg2=config/ ... will see 'cfg1' and 'cfg2=config' being added to the list of evsel config terms. Token 'cfg1' and 'cfg2=config' are not processed in user space and are meant to be interpreted by the PMU driver. First the lexer/parser are supplemented with the required definitions to recognise the driver specific configuration. From there they are simply added to the list of event terms. The bulk of the work is done in function "parse_events_add_pmu()" where driver config event terms are added to a new list of driver config terms, which in turn spliced with the event's new driver configuration list. Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> Acked-by: Jiri Olsa <jolsa@kernel.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/1473179837-3293-4-git-send-email-mathieu.poirier@linaro.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-record.txt12
-rw-r--r--tools/perf/util/evsel.h2
-rw-r--r--tools/perf/util/parse-events.c7
-rw-r--r--tools/perf/util/parse-events.h1
-rw-r--r--tools/perf/util/parse-events.l22
-rw-r--r--tools/perf/util/parse-events.y11
6 files changed, 54 insertions, 1 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 379a2bed07c0..1a24f4d64328 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -60,6 +60,18 @@ OPTIONS
60 Note: If user explicitly sets options which conflict with the params, 60 Note: If user explicitly sets options which conflict with the params,
61 the value set by the params will be overridden. 61 the value set by the params will be overridden.
62 62
63 Also not defined in .../<pmu>/format/* are PMU driver specific
64 configuration parameters. Any configuration parameter preceded by
65 the letter '@' is not interpreted in user space and sent down directly
66 to the PMU driver. For example:
67
68 perf record -e some_event/@cfg1,@cfg2=config/ ...
69
70 will see 'cfg1' and 'cfg2=config' pushed to the PMU driver associated
71 with the event for further processing. There is no restriction on
72 what the configuration parameters are, as long as their semantic is
73 understood and supported by the PMU driver.
74
63 - a hardware breakpoint event in the form of '\mem:addr[/len][:access]' 75 - a hardware breakpoint event in the form of '\mem:addr[/len][:access]'
64 where addr is the address in memory you want to break in. 76 where addr is the address in memory you want to break in.
65 Access is the memory access type (read, write, execute) it can 77 Access is the memory access type (read, write, execute) it can
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 4d44129e050b..323806082c58 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -46,6 +46,7 @@ enum {
46 PERF_EVSEL__CONFIG_TERM_INHERIT, 46 PERF_EVSEL__CONFIG_TERM_INHERIT,
47 PERF_EVSEL__CONFIG_TERM_MAX_STACK, 47 PERF_EVSEL__CONFIG_TERM_MAX_STACK,
48 PERF_EVSEL__CONFIG_TERM_OVERWRITE, 48 PERF_EVSEL__CONFIG_TERM_OVERWRITE,
49 PERF_EVSEL__CONFIG_TERM_DRV_CFG,
49 PERF_EVSEL__CONFIG_TERM_MAX, 50 PERF_EVSEL__CONFIG_TERM_MAX,
50}; 51};
51 52
@@ -57,6 +58,7 @@ struct perf_evsel_config_term {
57 u64 freq; 58 u64 freq;
58 bool time; 59 bool time;
59 char *callgraph; 60 char *callgraph;
61 char *drv_cfg;
60 u64 stack_user; 62 u64 stack_user;
61 int max_stack; 63 int max_stack;
62 bool inherit; 64 bool inherit;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 6c913c3914fb..2eb8b1ed4cc8 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -904,6 +904,7 @@ static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = {
904 [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack", 904 [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack",
905 [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite", 905 [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite",
906 [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite", 906 [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite",
907 [PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config",
907}; 908};
908 909
909static bool config_term_shrinked; 910static bool config_term_shrinked;
@@ -1034,7 +1035,8 @@ static int config_term_pmu(struct perf_event_attr *attr,
1034 struct parse_events_term *term, 1035 struct parse_events_term *term,
1035 struct parse_events_error *err) 1036 struct parse_events_error *err)
1036{ 1037{
1037 if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER) 1038 if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER ||
1039 term->type_term == PARSE_EVENTS__TERM_TYPE_DRV_CFG)
1038 /* 1040 /*
1039 * Always succeed for sysfs terms, as we dont know 1041 * Always succeed for sysfs terms, as we dont know
1040 * at this point what type they need to have. 1042 * at this point what type they need to have.
@@ -1134,6 +1136,9 @@ do { \
1134 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 1136 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
1135 ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 0 : 1); 1137 ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 0 : 1);
1136 break; 1138 break;
1139 case PARSE_EVENTS__TERM_TYPE_DRV_CFG:
1140 ADD_CONFIG_TERM(DRV_CFG, drv_cfg, term->val.str);
1141 break;
1137 default: 1142 default:
1138 break; 1143 break;
1139 } 1144 }
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index d1edbf8cc66a..8d09a976fca8 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -71,6 +71,7 @@ enum {
71 PARSE_EVENTS__TERM_TYPE_MAX_STACK, 71 PARSE_EVENTS__TERM_TYPE_MAX_STACK,
72 PARSE_EVENTS__TERM_TYPE_NOOVERWRITE, 72 PARSE_EVENTS__TERM_TYPE_NOOVERWRITE,
73 PARSE_EVENTS__TERM_TYPE_OVERWRITE, 73 PARSE_EVENTS__TERM_TYPE_OVERWRITE,
74 PARSE_EVENTS__TERM_TYPE_DRV_CFG,
74 __PARSE_EVENTS__TERM_TYPE_NR, 75 __PARSE_EVENTS__TERM_TYPE_NR,
75}; 76};
76 77
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 7a2519435da0..9f43fda2570f 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -53,6 +53,26 @@ static int str(yyscan_t scanner, int token)
53 return token; 53 return token;
54} 54}
55 55
56/*
57 * This function is called when the parser gets two kind of input:
58 *
59 * @cfg1 or @cfg2=config
60 *
61 * The leading '@' is stripped off before 'cfg1' and 'cfg2=config' are given to
62 * bison. In the latter case it is necessary to keep the string intact so that
63 * the PMU kernel driver can determine what configurable is associated to
64 * 'config'.
65 */
66static int drv_str(yyscan_t scanner, int token)
67{
68 YYSTYPE *yylval = parse_events_get_lval(scanner);
69 char *text = parse_events_get_text(scanner);
70
71 /* Strip off the '@' */
72 yylval->str = strdup(text + 1);
73 return token;
74}
75
56#define REWIND(__alloc) \ 76#define REWIND(__alloc) \
57do { \ 77do { \
58 YYSTYPE *__yylval = parse_events_get_lval(yyscanner); \ 78 YYSTYPE *__yylval = parse_events_get_lval(yyscanner); \
@@ -124,6 +144,7 @@ num_hex 0x[a-fA-F0-9]+
124num_raw_hex [a-fA-F0-9]+ 144num_raw_hex [a-fA-F0-9]+
125name [a-zA-Z_*?][a-zA-Z0-9_*?.]* 145name [a-zA-Z_*?][a-zA-Z0-9_*?.]*
126name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]* 146name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]*
147drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)?
127/* If you add a modifier you need to update check_modifier() */ 148/* If you add a modifier you need to update check_modifier() */
128modifier_event [ukhpPGHSDI]+ 149modifier_event [ukhpPGHSDI]+
129modifier_bp [rwx]{1,3} 150modifier_bp [rwx]{1,3}
@@ -209,6 +230,7 @@ no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); }
209{name_minus} { return str(yyscanner, PE_NAME); } 230{name_minus} { return str(yyscanner, PE_NAME); }
210\[all\] { return PE_ARRAY_ALL; } 231\[all\] { return PE_ARRAY_ALL; }
211"[" { BEGIN(array); return '['; } 232"[" { BEGIN(array); return '['; }
233@{drv_cfg_term} { return drv_str(yyscanner, PE_DRV_CFG_TERM); }
212} 234}
213 235
214<mem>{ 236<mem>{
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 5be4a5f216d6..879115f93edc 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -49,6 +49,7 @@ static void inc_group_count(struct list_head *list,
49%token PE_ERROR 49%token PE_ERROR
50%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT 50%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
51%token PE_ARRAY_ALL PE_ARRAY_RANGE 51%token PE_ARRAY_ALL PE_ARRAY_RANGE
52%token PE_DRV_CFG_TERM
52%type <num> PE_VALUE 53%type <num> PE_VALUE
53%type <num> PE_VALUE_SYM_HW 54%type <num> PE_VALUE_SYM_HW
54%type <num> PE_VALUE_SYM_SW 55%type <num> PE_VALUE_SYM_SW
@@ -63,6 +64,7 @@ static void inc_group_count(struct list_head *list,
63%type <str> PE_MODIFIER_BP 64%type <str> PE_MODIFIER_BP
64%type <str> PE_EVENT_NAME 65%type <str> PE_EVENT_NAME
65%type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT 66%type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
67%type <str> PE_DRV_CFG_TERM
66%type <num> value_sym 68%type <num> value_sym
67%type <head> event_config 69%type <head> event_config
68%type <head> opt_event_config 70%type <head> opt_event_config
@@ -599,6 +601,15 @@ PE_NAME array '=' PE_VALUE
599 term->array = $2; 601 term->array = $2;
600 $$ = term; 602 $$ = term;
601} 603}
604|
605PE_DRV_CFG_TERM
606{
607 struct parse_events_term *term;
608
609 ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG,
610 $1, $1, &@1, NULL));
611 $$ = term;
612}
602 613
603array: 614array:
604'[' array_terms ']' 615'[' array_terms ']'