4 #include "parse-options.h"
5 #include "parse-events.h"
9 extern char *strcasestr(const char *haystack
, const char *needle
);
13 struct perf_counter_attr attrs
[MAX_COUNTERS
];
21 #define C(x, y) .type = PERF_TYPE_##x, .config = PERF_COUNT_##y
22 #define CR(x, y) .type = PERF_TYPE_##x, .config = y
24 static struct event_symbol event_symbols
[] = {
25 { C(HARDWARE
, HW_CPU_CYCLES
), "cpu-cycles", },
26 { C(HARDWARE
, HW_CPU_CYCLES
), "cycles", },
27 { C(HARDWARE
, HW_INSTRUCTIONS
), "instructions", },
28 { C(HARDWARE
, HW_CACHE_REFERENCES
), "cache-references", },
29 { C(HARDWARE
, HW_CACHE_MISSES
), "cache-misses", },
30 { C(HARDWARE
, HW_BRANCH_INSTRUCTIONS
),"branch-instructions", },
31 { C(HARDWARE
, HW_BRANCH_INSTRUCTIONS
),"branches", },
32 { C(HARDWARE
, HW_BRANCH_MISSES
), "branch-misses", },
33 { C(HARDWARE
, HW_BUS_CYCLES
), "bus-cycles", },
35 { C(SOFTWARE
, SW_CPU_CLOCK
), "cpu-clock", },
36 { C(SOFTWARE
, SW_TASK_CLOCK
), "task-clock", },
37 { C(SOFTWARE
, SW_PAGE_FAULTS
), "page-faults", },
38 { C(SOFTWARE
, SW_PAGE_FAULTS
), "faults", },
39 { C(SOFTWARE
, SW_PAGE_FAULTS_MIN
), "minor-faults", },
40 { C(SOFTWARE
, SW_PAGE_FAULTS_MAJ
), "major-faults", },
41 { C(SOFTWARE
, SW_CONTEXT_SWITCHES
), "context-switches", },
42 { C(SOFTWARE
, SW_CONTEXT_SWITCHES
), "cs", },
43 { C(SOFTWARE
, SW_CPU_MIGRATIONS
), "cpu-migrations", },
44 { C(SOFTWARE
, SW_CPU_MIGRATIONS
), "migrations", },
47 #define __PERF_COUNTER_FIELD(config, name) \
48 ((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT)
50 #define PERF_COUNTER_RAW(config) __PERF_COUNTER_FIELD(config, RAW)
51 #define PERF_COUNTER_CONFIG(config) __PERF_COUNTER_FIELD(config, CONFIG)
52 #define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE)
53 #define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT)
55 static char *hw_event_names
[] = {
65 static char *sw_event_names
[] = {
77 static char *hw_cache
[][MAX_ALIASES
] = {
78 { "L1-data" , "l1-d", "l1d" },
79 { "L1-instruction" , "l1-i", "l1i" },
81 { "Data-TLB" , "dtlb", "d-tlb" },
82 { "Instruction-TLB" , "itlb", "i-tlb" },
83 { "Branch" , "bpu" , "btb", "bpc" },
86 static char *hw_cache_op
[][MAX_ALIASES
] = {
88 { "Store" , "write" },
89 { "Prefetch" , "speculative-read", "speculative-load" },
92 static char *hw_cache_result
[][MAX_ALIASES
] = {
93 { "Reference" , "ops", "access" },
97 char *event_name(int counter
)
99 u64 config
= attrs
[counter
].config
;
100 int type
= attrs
[counter
].type
;
103 if (attrs
[counter
].type
== PERF_TYPE_RAW
) {
104 sprintf(buf
, "raw 0x%llx", config
);
109 case PERF_TYPE_HARDWARE
:
110 if (config
< PERF_COUNT_HW_MAX
)
111 return hw_event_names
[config
];
112 return "unknown-hardware";
114 case PERF_TYPE_HW_CACHE
: {
115 u8 cache_type
, cache_op
, cache_result
;
116 static char name
[100];
118 cache_type
= (config
>> 0) & 0xff;
119 if (cache_type
> PERF_COUNT_HW_CACHE_MAX
)
120 return "unknown-ext-hardware-cache-type";
122 cache_op
= (config
>> 8) & 0xff;
123 if (cache_op
> PERF_COUNT_HW_CACHE_OP_MAX
)
124 return "unknown-ext-hardware-cache-op";
126 cache_result
= (config
>> 16) & 0xff;
127 if (cache_result
> PERF_COUNT_HW_CACHE_RESULT_MAX
)
128 return "unknown-ext-hardware-cache-result";
130 sprintf(name
, "%s-Cache-%s-%ses",
131 hw_cache
[cache_type
][0],
132 hw_cache_op
[cache_op
][0],
133 hw_cache_result
[cache_result
][0]);
138 case PERF_TYPE_SOFTWARE
:
139 if (config
< PERF_COUNT_SW_MAX
)
140 return sw_event_names
[config
];
141 return "unknown-software";
150 static int parse_aliases(const char *str
, char *names
[][MAX_ALIASES
], int size
)
154 for (i
= 0; i
< size
; i
++) {
155 for (j
= 0; j
< MAX_ALIASES
; j
++) {
158 if (strcasestr(str
, names
[i
][j
]))
166 static int parse_generic_hw_symbols(const char *str
, struct perf_counter_attr
*attr
)
168 int cache_type
= -1, cache_op
= 0, cache_result
= 0;
170 cache_type
= parse_aliases(str
, hw_cache
, PERF_COUNT_HW_CACHE_MAX
);
172 * No fallback - if we cannot get a clear cache type
175 if (cache_type
== -1)
178 cache_op
= parse_aliases(str
, hw_cache_op
, PERF_COUNT_HW_CACHE_OP_MAX
);
180 * Fall back to reads:
183 cache_op
= PERF_COUNT_HW_CACHE_OP_READ
;
185 cache_result
= parse_aliases(str
, hw_cache_result
,
186 PERF_COUNT_HW_CACHE_RESULT_MAX
);
188 * Fall back to accesses:
190 if (cache_result
== -1)
191 cache_result
= PERF_COUNT_HW_CACHE_RESULT_ACCESS
;
193 attr
->config
= cache_type
| (cache_op
<< 8) | (cache_result
<< 16);
194 attr
->type
= PERF_TYPE_HW_CACHE
;
200 * Each event can have multiple symbolic names.
201 * Symbolic names are (almost) exactly matched.
203 static int parse_event_symbols(const char *str
, struct perf_counter_attr
*attr
)
208 const char *sep
, *pstr
;
210 if (str
[0] == 'r' && hex2u64(str
+ 1, &config
) > 0) {
211 attr
->type
= PERF_TYPE_RAW
;
212 attr
->config
= config
;
218 sep
= strchr(pstr
, ':');
223 sep
= strchr(pstr
, ':');
226 if (strchr(pstr
, 'k'))
227 attr
->exclude_user
= 1;
228 if (strchr(pstr
, 'u'))
229 attr
->exclude_kernel
= 1;
237 for (i
= 0; i
< ARRAY_SIZE(event_symbols
); i
++) {
238 if (!strncmp(str
, event_symbols
[i
].symbol
,
239 strlen(event_symbols
[i
].symbol
))) {
241 attr
->type
= event_symbols
[i
].type
;
242 attr
->config
= event_symbols
[i
].config
;
248 return parse_generic_hw_symbols(str
, attr
);
251 int parse_events(const struct option
*opt
, const char *str
, int unset
)
253 struct perf_counter_attr attr
;
256 memset(&attr
, 0, sizeof(attr
));
258 if (nr_counters
== MAX_COUNTERS
)
261 ret
= parse_event_symbols(str
, &attr
);
265 attrs
[nr_counters
] = attr
;
268 str
= strstr(str
, ",");
277 static const char * const event_type_descriptors
[] = {
282 "Hardware cache event",
286 * Print the help text for the event symbols:
288 void print_events(void)
290 struct event_symbol
*syms
= event_symbols
;
291 unsigned int i
, type
, prev_type
= -1;
293 fprintf(stderr
, "\n");
294 fprintf(stderr
, "List of pre-defined events (to be used in -e):\n");
296 for (i
= 0; i
< ARRAY_SIZE(event_symbols
); i
++, syms
++) {
297 type
= syms
->type
+ 1;
298 if (type
> ARRAY_SIZE(event_type_descriptors
))
301 if (type
!= prev_type
)
302 fprintf(stderr
, "\n");
304 fprintf(stderr
, " %-30s [%s]\n", syms
->symbol
,
305 event_type_descriptors
[type
]);
310 fprintf(stderr
, "\n");
311 fprintf(stderr
, " %-30s [raw hardware event descriptor]\n",
313 fprintf(stderr
, "\n");