diff options
| -rw-r--r-- | tools/perf/util/evsel.c | 104 | ||||
| -rw-r--r-- | tools/perf/util/evsel.h | 16 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.c | 115 | 
3 files changed, 134 insertions, 101 deletions
| diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index dab893804a14..47f1fe2feab8 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -128,6 +128,105 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)  	return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);  } +const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX] +				[PERF_EVSEL__MAX_ALIASES] = { + { "L1-dcache",	"l1-d",		"l1d",		"L1-data",		}, + { "L1-icache",	"l1-i",		"l1i",		"L1-instruction",	}, + { "LLC",	"L2",							}, + { "dTLB",	"d-tlb",	"Data-TLB",				}, + { "iTLB",	"i-tlb",	"Instruction-TLB",			}, + { "branch",	"branches",	"bpu",		"btb",		"bpc",	}, + { "node",								}, +}; + +const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX] +				   [PERF_EVSEL__MAX_ALIASES] = { + { "load",	"loads",	"read",					}, + { "store",	"stores",	"write",				}, + { "prefetch",	"prefetches",	"speculative-read", "speculative-load",	}, +}; + +const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX] +				       [PERF_EVSEL__MAX_ALIASES] = { + { "refs",	"Reference",	"ops",		"access",		}, + { "misses",	"miss",							}, +}; + +#define C(x)		PERF_COUNT_HW_CACHE_##x +#define CACHE_READ	(1 << C(OP_READ)) +#define CACHE_WRITE	(1 << C(OP_WRITE)) +#define CACHE_PREFETCH	(1 << C(OP_PREFETCH)) +#define COP(x)		(1 << x) + +/* + * cache operartion stat + * L1I : Read and prefetch only + * ITLB and BPU : Read-only + */ +static unsigned long perf_evsel__hw_cache_stat[C(MAX)] = { + [C(L1D)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), + [C(L1I)]	= (CACHE_READ | CACHE_PREFETCH), + [C(LL)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), + [C(DTLB)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), + [C(ITLB)]	= (CACHE_READ), + [C(BPU)]	= (CACHE_READ), + [C(NODE)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), +}; + +bool perf_evsel__is_cache_op_valid(u8 type, u8 op) +{ +	if (perf_evsel__hw_cache_stat[type] & COP(op)) +		return true;	/* valid */ +	else +		return false;	/* invalid */ +} + +int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, +					    char *bf, size_t size) +{ +	if (result) { +		return scnprintf(bf, size, "%s-%s-%s", perf_evsel__hw_cache[type][0], +				 perf_evsel__hw_cache_op[op][0], +				 perf_evsel__hw_cache_result[result][0]); +	} + +	return scnprintf(bf, size, "%s-%s", perf_evsel__hw_cache[type][0], +			 perf_evsel__hw_cache_op[op][1]); +} + +int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size) +{ +	u8 op, result, type = (config >>  0) & 0xff; +	const char *err = "unknown-ext-hardware-cache-type"; + +	if (type > PERF_COUNT_HW_CACHE_MAX) +		goto out_err; + +	op = (config >>  8) & 0xff; +	err = "unknown-ext-hardware-cache-op"; +	if (op > PERF_COUNT_HW_CACHE_OP_MAX) +		goto out_err; + +	result = (config >> 16) & 0xff; +	err = "unknown-ext-hardware-cache-result"; +	if (result > PERF_COUNT_HW_CACHE_RESULT_MAX) +		goto out_err; + +	err = "invalid-cache"; +	if (!perf_evsel__is_cache_op_valid(type, op)) +		goto out_err; + +	return __perf_evsel__hw_cache_type_op_res_name(type, op, result, bf, size); +out_err: +	return scnprintf(bf, size, "%s", err); +} + +static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t size) +{ +	int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size); +	return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret); +} +  int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size)  {  	int ret; @@ -140,6 +239,11 @@ int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size)  	case PERF_TYPE_HARDWARE:  		ret = perf_evsel__hw_name(evsel, bf, size);  		break; + +	case PERF_TYPE_HW_CACHE: +		ret = perf_evsel__hw_cache_name(evsel, bf, size); +		break; +  	default:  		/*  		 * FIXME diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 4ba8b564e6f4..5bf946a05a6b 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -83,7 +83,21 @@ void perf_evsel__config(struct perf_evsel *evsel,  			struct perf_record_opts *opts,  			struct perf_evsel *first); -const char* __perf_evsel__hw_name(u64 config); +bool perf_evsel__is_cache_op_valid(u8 type, u8 op); + +#define PERF_EVSEL__MAX_ALIASES 8 + +extern const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX] +				       [PERF_EVSEL__MAX_ALIASES]; +extern const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX] +					  [PERF_EVSEL__MAX_ALIASES]; +const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX] +				       [PERF_EVSEL__MAX_ALIASES]; +int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, +					    char *bf, size_t size); +int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size); + +const char *__perf_evsel__hw_name(u64 config);  int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size);  int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 05dbc8b3c767..c8f8cf4a6920 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -74,51 +74,6 @@ static const char *sw_event_names[PERF_COUNT_SW_MAX] = {  	"emulation-faults",  }; -#define MAX_ALIASES 8 - -static const char *hw_cache[PERF_COUNT_HW_CACHE_MAX][MAX_ALIASES] = { - { "L1-dcache",	"l1-d",		"l1d",		"L1-data",		}, - { "L1-icache",	"l1-i",		"l1i",		"L1-instruction",	}, - { "LLC",	"L2",							}, - { "dTLB",	"d-tlb",	"Data-TLB",				}, - { "iTLB",	"i-tlb",	"Instruction-TLB",			}, - { "branch",	"branches",	"bpu",		"btb",		"bpc",	}, - { "node",								}, -}; - -static const char *hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX][MAX_ALIASES] = { - { "load",	"loads",	"read",					}, - { "store",	"stores",	"write",				}, - { "prefetch",	"prefetches",	"speculative-read", "speculative-load",	}, -}; - -static const char *hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX] -				  [MAX_ALIASES] = { - { "refs",	"Reference",	"ops",		"access",		}, - { "misses",	"miss",							}, -}; - -#define C(x)		PERF_COUNT_HW_CACHE_##x -#define CACHE_READ	(1 << C(OP_READ)) -#define CACHE_WRITE	(1 << C(OP_WRITE)) -#define CACHE_PREFETCH	(1 << C(OP_PREFETCH)) -#define COP(x)		(1 << x) - -/* - * cache operartion stat - * L1I : Read and prefetch only - * ITLB and BPU : Read-only - */ -static unsigned long hw_cache_stat[C(MAX)] = { - [C(L1D)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), - [C(L1I)]	= (CACHE_READ | CACHE_PREFETCH), - [C(LL)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), - [C(DTLB)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), - [C(ITLB)]	= (CACHE_READ), - [C(BPU)]	= (CACHE_READ), - [C(NODE)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), -}; -  #define for_each_subsystem(sys_dir, sys_dirent, sys_next)	       \  	while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)	       \  	if (sys_dirent.d_type == DT_DIR &&				       \ @@ -236,30 +191,6 @@ static const char *tracepoint_id_to_name(u64 config)  	return buf;  } -static int is_cache_op_valid(u8 cache_type, u8 cache_op) -{ -	if (hw_cache_stat[cache_type] & COP(cache_op)) -		return 1;	/* valid */ -	else -		return 0;	/* invalid */ -} - -static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result) -{ -	static char name[50]; - -	if (cache_result) { -		sprintf(name, "%s-%s-%s", hw_cache[cache_type][0], -			hw_cache_op[cache_op][0], -			hw_cache_result[cache_result][0]); -	} else { -		sprintf(name, "%s-%s", hw_cache[cache_type][0], -			hw_cache_op[cache_op][1]); -	} - -	return name; -} -  const char *event_type(int type)  {  	switch (type) { @@ -287,7 +218,7 @@ const char *event_name(struct perf_evsel *evsel)  	u64 config = evsel->attr.config;  	int type = evsel->attr.type; -	if (type == PERF_TYPE_RAW || type == PERF_TYPE_HARDWARE) { +	if (type == PERF_TYPE_RAW || type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE) {  		/*   		 * XXX minimal fix, see comment on perf_evsen__name, this static buffer   		 * will go away together with event_name in the next devel cycle. @@ -316,26 +247,9 @@ const char *__event_name(int type, u64 config)  	case PERF_TYPE_HARDWARE:  		return __perf_evsel__hw_name(config); -	case PERF_TYPE_HW_CACHE: { -		u8 cache_type, cache_op, cache_result; - -		cache_type   = (config >>  0) & 0xff; -		if (cache_type > PERF_COUNT_HW_CACHE_MAX) -			return "unknown-ext-hardware-cache-type"; - -		cache_op     = (config >>  8) & 0xff; -		if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX) -			return "unknown-ext-hardware-cache-op"; - -		cache_result = (config >> 16) & 0xff; -		if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX) -			return "unknown-ext-hardware-cache-result"; - -		if (!is_cache_op_valid(cache_type, cache_op)) -			return "invalid-cache"; - -		return event_cache_name(cache_type, cache_op, cache_result); -	} +	case PERF_TYPE_HW_CACHE: +		__perf_evsel__hw_cache_name(config, buf, sizeof(buf)); +		return buf;  	case PERF_TYPE_SOFTWARE:  		if (config < PERF_COUNT_SW_MAX && sw_event_names[config]) @@ -379,13 +293,13 @@ static int add_event(struct list_head **_list, int *idx,  	return 0;  } -static int parse_aliases(char *str, const char *names[][MAX_ALIASES], int size) +static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)  {  	int i, j;  	int n, longest = -1;  	for (i = 0; i < size; i++) { -		for (j = 0; j < MAX_ALIASES && names[i][j]; j++) { +		for (j = 0; j < PERF_EVSEL__MAX_ALIASES && names[i][j]; j++) {  			n = strlen(names[i][j]);  			if (n > longest && !strncasecmp(str, names[i][j], n))  				longest = n; @@ -410,7 +324,7 @@ int parse_events_add_cache(struct list_head **list, int *idx,  	 * No fallback - if we cannot get a clear cache type  	 * then bail out:  	 */ -	cache_type = parse_aliases(type, hw_cache, +	cache_type = parse_aliases(type, perf_evsel__hw_cache,  				   PERF_COUNT_HW_CACHE_MAX);  	if (cache_type == -1)  		return -EINVAL; @@ -423,18 +337,18 @@ int parse_events_add_cache(struct list_head **list, int *idx,  		snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str);  		if (cache_op == -1) { -			cache_op = parse_aliases(str, hw_cache_op, +			cache_op = parse_aliases(str, perf_evsel__hw_cache_op,  						 PERF_COUNT_HW_CACHE_OP_MAX);  			if (cache_op >= 0) { -				if (!is_cache_op_valid(cache_type, cache_op)) +				if (!perf_evsel__is_cache_op_valid(cache_type, cache_op))  					return -EINVAL;  				continue;  			}  		}  		if (cache_result == -1) { -			cache_result = parse_aliases(str, hw_cache_result, -						PERF_COUNT_HW_CACHE_RESULT_MAX); +			cache_result = parse_aliases(str, perf_evsel__hw_cache_result, +						     PERF_COUNT_HW_CACHE_RESULT_MAX);  			if (cache_result >= 0)  				continue;  		} @@ -970,16 +884,17 @@ void print_events_type(u8 type)  int print_hwcache_events(const char *event_glob)  {  	unsigned int type, op, i, printed = 0; +	char name[64];  	for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {  		for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {  			/* skip invalid cache type */ -			if (!is_cache_op_valid(type, op)) +			if (!perf_evsel__is_cache_op_valid(type, op))  				continue;  			for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { -				char *name = event_cache_name(type, op, i); - +				__perf_evsel__hw_cache_type_op_res_name(type, op, i, +									name, sizeof(name));  				if (event_glob != NULL && !strglobmatch(name, event_glob))  					continue; | 
