Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent c8defe24
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -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 {
+63 −11
Original line number Original line Diff line number Diff line
@@ -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,
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,
	}
	}


	/*
	/*
	 * 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,
{
{
	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;
}
}