Commit 688d4dfc authored by Cody P Schafer's avatar Cody P Schafer Committed by Arnaldo Carvalho de Melo

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: default avatarCody P Schafer <cody@linux.vnet.ibm.com>
Signed-off-by: default avatarSukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Acked-by: default avatarJiri 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.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent c8defe24
...@@ -71,6 +71,7 @@ struct parse_events_term { ...@@ -71,6 +71,7 @@ struct parse_events_term {
int type_val; int type_val;
int type_term; int type_term;
struct list_head list; struct list_head list;
bool used;
}; };
struct parse_events_evlist { struct parse_events_evlist {
......
...@@ -550,6 +550,35 @@ static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, ...@@ -550,6 +550,35 @@ static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
} }
} }
/*
* Term is a string term, and might be a param-term. Try to look up it's value
* in the remaining terms.
* - We have a term like "base-or-format-term=param-term",
* - We need to find the value supplied for "param-term" (with param-term named
* in a config string) later on in the term list.
*/
static int pmu_resolve_param_term(struct parse_events_term *term,
struct list_head *head_terms,
__u64 *value)
{
struct parse_events_term *t;
list_for_each_entry(t, head_terms, list) {
if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
if (!strcmp(t->config, term->config)) {
t->used = true;
*value = t->val.num;
return 0;
}
}
}
if (verbose)
printf("Required parameter '%s' not specified\n", term->config);
return -1;
}
/* /*
* Setup one of config[12] attr members based on the * Setup one of config[12] attr members based on the
* user input data - term parameter. * user input data - term parameter.
...@@ -557,25 +586,33 @@ static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, ...@@ -557,25 +586,33 @@ static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
static int pmu_config_term(struct list_head *formats, static int pmu_config_term(struct list_head *formats,
struct perf_event_attr *attr, struct perf_event_attr *attr,
struct parse_events_term *term, struct parse_events_term *term,
struct list_head *head_terms,
bool zero) bool zero)
{ {
struct perf_pmu_format *format; struct perf_pmu_format *format;
__u64 *vp; __u64 *vp;
__u64 val;
/*
* If this is a parameter we've already used for parameterized-eval,
* skip it in normal eval.
*/
if (term->used)
return 0;
/* /*
* Support only for hardcoded and numnerial terms.
* Hardcoded terms should be already in, so nothing * Hardcoded terms should be already in, so nothing
* to be done for them. * to be done for them.
*/ */
if (parse_events__is_hardcoded_term(term)) if (parse_events__is_hardcoded_term(term))
return 0; return 0;
if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM)
return -EINVAL;
format = pmu_find_format(formats, term->config); format = pmu_find_format(formats, term->config);
if (!format) if (!format) {
if (verbose)
printf("Invalid event/parameter '%s'\n", term->config);
return -EINVAL; return -EINVAL;
}
switch (format->value) { switch (format->value) {
case PERF_PMU_FORMAT_VALUE_CONFIG: case PERF_PMU_FORMAT_VALUE_CONFIG:
...@@ -592,11 +629,25 @@ static int pmu_config_term(struct list_head *formats, ...@@ -592,11 +629,25 @@ static int pmu_config_term(struct list_head *formats,
} }
/* /*
* XXX If we ever decide to go with string values for * Either directly use a numeric term, or try to translate string terms
* non-hardcoded terms, here's the place to translate * using event parameters.
* them into value.
*/ */
pmu_format_value(format->bits, term->val.num, vp, zero); if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM)
val = term->val.num;
else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
if (strcmp(term->val.str, "?")) {
if (verbose)
pr_info("Invalid sysfs entry %s=%s\n",
term->config, term->val.str);
return -EINVAL;
}
if (pmu_resolve_param_term(term, head_terms, &val))
return -EINVAL;
} else
return -EINVAL;
pmu_format_value(format->bits, val, vp, zero);
return 0; return 0;
} }
...@@ -607,9 +658,10 @@ int perf_pmu__config_terms(struct list_head *formats, ...@@ -607,9 +658,10 @@ int perf_pmu__config_terms(struct list_head *formats,
{ {
struct parse_events_term *term; struct parse_events_term *term;
list_for_each_entry(term, head_terms, list) list_for_each_entry(term, head_terms, list) {
if (pmu_config_term(formats, attr, term, zero)) if (pmu_config_term(formats, attr, term, head_terms, zero))
return -EINVAL; return -EINVAL;
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment