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
];
22 #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
23 #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
25 static struct event_symbol event_symbols
[] = {
26 { CHW(CPU_CYCLES
), "cpu-cycles", "cycles" },
27 { CHW(INSTRUCTIONS
), "instructions", "" },
28 { CHW(CACHE_REFERENCES
), "cache-references", "" },
29 { CHW(CACHE_MISSES
), "cache-misses", "" },
30 { CHW(BRANCH_INSTRUCTIONS
), "branch-instructions", "branches" },
31 { CHW(BRANCH_MISSES
), "branch-misses", "" },
32 { CHW(BUS_CYCLES
), "bus-cycles", "" },
34 { CSW(CPU_CLOCK
), "cpu-clock", "" },
35 { CSW(TASK_CLOCK
), "task-clock", "" },
36 { CSW(PAGE_FAULTS
), "page-faults", "" },
37 { CSW(PAGE_FAULTS
), "faults", "" },
38 { CSW(PAGE_FAULTS_MIN
), "minor-faults", "" },
39 { CSW(PAGE_FAULTS_MAJ
), "major-faults", "" },
40 { CSW(CONTEXT_SWITCHES
), "context-switches", "cs" },
41 { CSW(CPU_MIGRATIONS
), "cpu-migrations", "migrations" },
44 #define __PERF_COUNTER_FIELD(config, name) \
45 ((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT)
47 #define PERF_COUNTER_RAW(config) __PERF_COUNTER_FIELD(config, RAW)
48 #define PERF_COUNTER_CONFIG(config) __PERF_COUNTER_FIELD(config, CONFIG)
49 #define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE)
50 #define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT)
52 static char *hw_event_names
[] = {
62 static char *sw_event_names
[] = {
74 static char *hw_cache
[][MAX_ALIASES
] = {
75 { "L1-data" , "l1-d", "l1d" },
76 { "L1-instruction" , "l1-i", "l1i" },
78 { "Data-TLB" , "dtlb", "d-tlb" },
79 { "Instruction-TLB" , "itlb", "i-tlb" },
80 { "Branch" , "bpu" , "btb", "bpc" },
83 static char *hw_cache_op
[][MAX_ALIASES
] = {
85 { "Store" , "write" },
86 { "Prefetch" , "speculative-read", "speculative-load" },
89 static char *hw_cache_result
[][MAX_ALIASES
] = {
90 { "Reference" , "ops", "access" },
94 char *event_name(int counter
)
96 u64 config
= attrs
[counter
].config
;
97 int type
= attrs
[counter
].type
;
100 if (attrs
[counter
].type
== PERF_TYPE_RAW
) {
101 sprintf(buf
, "raw 0x%llx", config
);
106 case PERF_TYPE_HARDWARE
:
107 if (config
< PERF_COUNT_HW_MAX
)
108 return hw_event_names
[config
];
109 return "unknown-hardware";
111 case PERF_TYPE_HW_CACHE
: {
112 u8 cache_type
, cache_op
, cache_result
;
113 static char name
[100];
115 cache_type
= (config
>> 0) & 0xff;
116 if (cache_type
> PERF_COUNT_HW_CACHE_MAX
)
117 return "unknown-ext-hardware-cache-type";
119 cache_op
= (config
>> 8) & 0xff;
120 if (cache_op
> PERF_COUNT_HW_CACHE_OP_MAX
)
121 return "unknown-ext-hardware-cache-op";
123 cache_result
= (config
>> 16) & 0xff;
124 if (cache_result
> PERF_COUNT_HW_CACHE_RESULT_MAX
)
125 return "unknown-ext-hardware-cache-result";
127 sprintf(name
, "%s-Cache-%s-%ses",
128 hw_cache
[cache_type
][0],
129 hw_cache_op
[cache_op
][0],
130 hw_cache_result
[cache_result
][0]);
135 case PERF_TYPE_SOFTWARE
:
136 if (config
< PERF_COUNT_SW_MAX
)
137 return sw_event_names
[config
];
138 return "unknown-software";
147 static int parse_aliases(const char *str
, char *names
[][MAX_ALIASES
], int size
)
151 for (i
= 0; i
< size
; i
++) {
152 for (j
= 0; j
< MAX_ALIASES
; j
++) {
155 if (strcasestr(str
, names
[i
][j
]))
163 static int parse_generic_hw_symbols(const char *str
, struct perf_counter_attr
*attr
)
165 int cache_type
= -1, cache_op
= 0, cache_result
= 0;
167 cache_type
= parse_aliases(str
, hw_cache
, PERF_COUNT_HW_CACHE_MAX
);
169 * No fallback - if we cannot get a clear cache type
172 if (cache_type
== -1)
175 cache_op
= parse_aliases(str
, hw_cache_op
, PERF_COUNT_HW_CACHE_OP_MAX
);
177 * Fall back to reads:
180 cache_op
= PERF_COUNT_HW_CACHE_OP_READ
;
182 cache_result
= parse_aliases(str
, hw_cache_result
,
183 PERF_COUNT_HW_CACHE_RESULT_MAX
);
185 * Fall back to accesses:
187 if (cache_result
== -1)
188 cache_result
= PERF_COUNT_HW_CACHE_RESULT_ACCESS
;
190 attr
->config
= cache_type
| (cache_op
<< 8) | (cache_result
<< 16);
191 attr
->type
= PERF_TYPE_HW_CACHE
;
196 static int check_events(const char *str
, unsigned int i
)
198 if (!strncmp(str
, event_symbols
[i
].symbol
,
199 strlen(event_symbols
[i
].symbol
)))
202 if (strlen(event_symbols
[i
].alias
))
203 if (!strncmp(str
, event_symbols
[i
].alias
,
204 strlen(event_symbols
[i
].alias
)))
210 * Each event can have multiple symbolic names.
211 * Symbolic names are (almost) exactly matched.
213 static int parse_event_symbols(const char *str
, struct perf_counter_attr
*attr
)
218 const char *sep
, *pstr
;
220 if (str
[0] == 'r' && hex2u64(str
+ 1, &config
) > 0) {
221 attr
->type
= PERF_TYPE_RAW
;
222 attr
->config
= config
;
228 sep
= strchr(pstr
, ':');
233 sep
= strchr(pstr
, ':');
236 if (strchr(pstr
, 'k'))
237 attr
->exclude_user
= 1;
238 if (strchr(pstr
, 'u'))
239 attr
->exclude_kernel
= 1;
247 for (i
= 0; i
< ARRAY_SIZE(event_symbols
); i
++) {
248 if (check_events(str
, i
)) {
249 attr
->type
= event_symbols
[i
].type
;
250 attr
->config
= event_symbols
[i
].config
;
256 return parse_generic_hw_symbols(str
, attr
);
259 int parse_events(const struct option
*opt
, const char *str
, int unset
)
261 struct perf_counter_attr attr
;
264 memset(&attr
, 0, sizeof(attr
));
266 if (nr_counters
== MAX_COUNTERS
)
269 ret
= parse_event_symbols(str
, &attr
);
273 attrs
[nr_counters
] = attr
;
276 str
= strstr(str
, ",");
285 static const char * const event_type_descriptors
[] = {
290 "Hardware cache event",
294 * Print the help text for the event symbols:
296 void print_events(void)
298 struct event_symbol
*syms
= event_symbols
;
299 unsigned int i
, type
, prev_type
= -1;
302 fprintf(stderr
, "\n");
303 fprintf(stderr
, "List of pre-defined events (to be used in -e):\n");
305 for (i
= 0; i
< ARRAY_SIZE(event_symbols
); i
++, syms
++) {
306 type
= syms
->type
+ 1;
307 if (type
> ARRAY_SIZE(event_type_descriptors
))
310 if (type
!= prev_type
)
311 fprintf(stderr
, "\n");
313 if (strlen(syms
->alias
))
314 sprintf(name
, "%s OR %s", syms
->symbol
, syms
->alias
);
316 strcpy(name
, syms
->symbol
);
317 fprintf(stderr
, " %-40s [%s]\n", name
,
318 event_type_descriptors
[type
]);
323 fprintf(stderr
, "\n");
324 fprintf(stderr
, " %-40s [raw hardware event descriptor]\n",
326 fprintf(stderr
, "\n");