diff options
| author | Mark Brown <[email protected]> | 2015-10-12 18:09:27 +0100 | 
|---|---|---|
| committer | Mark Brown <[email protected]> | 2015-10-12 18:09:27 +0100 | 
| commit | 79828b4fa835f73cdaf4bffa48696abdcbea9d02 (patch) | |
| tree | 5e0fa7156acb75ba603022bc807df8f2fedb97a8 /tools/perf/util/pmu.c | |
| parent | 721b51fcf91898299d96f4b72cb9434cda29dce6 (diff) | |
| parent | 8c1a9d6323abf0fb1e5dad96cf3f1c783505ea5a (diff) | |
Merge remote-tracking branch 'asoc/fix/rt5645' into asoc-fix-rt5645
Diffstat (limited to 'tools/perf/util/pmu.c')
| -rw-r--r-- | tools/perf/util/pmu.c | 55 | 
1 files changed, 48 insertions, 7 deletions
| diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 7bcb8c315615..89c91a1a67e7 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -462,10 +462,6 @@ static struct perf_pmu *pmu_lookup(const char *name)  	LIST_HEAD(aliases);  	__u32 type; -	/* No support for intel_bts or intel_pt so disallow them */ -	if (!strcmp(name, "intel_bts") || !strcmp(name, "intel_pt")) -		return NULL; -  	/*  	 * The pmu data we store & need consists of the pmu  	 * type value and format definitions. Load both right @@ -542,7 +538,7 @@ struct perf_pmu *perf_pmu__find(const char *name)  }  static struct perf_pmu_format * -pmu_find_format(struct list_head *formats, char *name) +pmu_find_format(struct list_head *formats, const char *name)  {  	struct perf_pmu_format *format; @@ -553,6 +549,21 @@ pmu_find_format(struct list_head *formats, char *name)  	return NULL;  } +__u64 perf_pmu__format_bits(struct list_head *formats, const char *name) +{ +	struct perf_pmu_format *format = pmu_find_format(formats, name); +	__u64 bits = 0; +	int fbit; + +	if (!format) +		return 0; + +	for_each_set_bit(fbit, format->bits, PERF_PMU_FORMAT_BITS) +		bits |= 1ULL << fbit; + +	return bits; +} +  /*   * Sets value based on the format definition (format parameter)   * and unformated value (value parameter). @@ -574,6 +585,18 @@ static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,  	}  } +static __u64 pmu_format_max_value(const unsigned long *format) +{ +	int w; + +	w = bitmap_weight(format, PERF_PMU_FORMAT_BITS); +	if (!w) +		return 0; +	if (w < 64) +		return (1ULL << w) - 1; +	return -1; +} +  /*   * Term is a string term, and might be a param-term. Try to look up it's value   * in the remaining terms. @@ -607,7 +630,9 @@ static char *formats_error_string(struct list_head *formats)  {  	struct perf_pmu_format *format;  	char *err, *str; -	static const char *static_terms = "config,config1,config2,name,period,branch_type\n"; +	static const char *static_terms = "config,config1,config2,name," +					  "period,freq,branch_type,time," +					  "call-graph,stack-size\n";  	unsigned i = 0;  	if (!asprintf(&str, "valid terms:")) @@ -647,7 +672,7 @@ static int pmu_config_term(struct list_head *formats,  {  	struct perf_pmu_format *format;  	__u64 *vp; -	__u64 val; +	__u64 val, max_val;  	/*  	 * If this is a parameter we've already used for parameterized-eval, @@ -713,6 +738,22 @@ static int pmu_config_term(struct list_head *formats,  	} else  		return -EINVAL; +	max_val = pmu_format_max_value(format->bits); +	if (val > max_val) { +		if (err) { +			err->idx = term->err_val; +			if (asprintf(&err->str, +				     "value too big for format, maximum is %llu", +				     (unsigned long long)max_val) < 0) +				err->str = strdup("value too big for format"); +			return -EINVAL; +		} +		/* +		 * Assume we don't care if !err, in which case the value will be +		 * silently truncated. +		 */ +	} +  	pmu_format_value(format->bits, val, vp, zero);  	return 0;  } |