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>
This commit is contained in:
Родитель
c8defe2494
Коммит
688d4dfcdd
|
@ -71,6 +71,7 @@ struct parse_events_term {
|
|||
int type_val;
|
||||
int type_term;
|
||||
struct list_head list;
|
||||
bool used;
|
||||
};
|
||||
|
||||
struct parse_events_evlist {
|
||||
|
|
|
@ -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
|
||||
* user input data - term parameter.
|
||||
|
@ -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,
|
||||
struct perf_event_attr *attr,
|
||||
struct parse_events_term *term,
|
||||
struct list_head *head_terms,
|
||||
bool zero)
|
||||
{
|
||||
struct perf_pmu_format *format;
|
||||
__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
|
||||
* to be done for them.
|
||||
*/
|
||||
if (parse_events__is_hardcoded_term(term))
|
||||
return 0;
|
||||
|
||||
if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM)
|
||||
return -EINVAL;
|
||||
|
||||
format = pmu_find_format(formats, term->config);
|
||||
if (!format)
|
||||
if (!format) {
|
||||
if (verbose)
|
||||
printf("Invalid event/parameter '%s'\n", term->config);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (format->value) {
|
||||
case PERF_PMU_FORMAT_VALUE_CONFIG:
|
||||
|
@ -592,11 +629,25 @@ static int pmu_config_term(struct list_head *formats,
|
|||
}
|
||||
|
||||
/*
|
||||
* XXX If we ever decide to go with string values for
|
||||
* non-hardcoded terms, here's the place to translate
|
||||
* them into value.
|
||||
* Either directly use a numeric term, or try to translate string terms
|
||||
* using event parameters.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -607,9 +658,10 @@ int perf_pmu__config_terms(struct list_head *formats,
|
|||
{
|
||||
struct parse_events_term *term;
|
||||
|
||||
list_for_each_entry(term, head_terms, list)
|
||||
if (pmu_config_term(formats, attr, term, zero))
|
||||
list_for_each_entry(term, head_terms, list) {
|
||||
if (pmu_config_term(formats, attr, term, head_terms, zero))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче