186470930SIngo Molnar 286470930SIngo Molnar #include "../perf.h" 386470930SIngo Molnar #include "util.h" 486470930SIngo Molnar #include "parse-options.h" 586470930SIngo Molnar #include "parse-events.h" 686470930SIngo Molnar #include "exec_cmd.h" 786470930SIngo Molnar #include "string.h" 886470930SIngo Molnar 986470930SIngo Molnar extern char *strcasestr(const char *haystack, const char *needle); 1086470930SIngo Molnar 1186470930SIngo Molnar int nr_counters; 1286470930SIngo Molnar 1386470930SIngo Molnar struct perf_counter_attr attrs[MAX_COUNTERS]; 1486470930SIngo Molnar 1586470930SIngo Molnar struct event_symbol { 169cffa8d5SPaul Mackerras u8 type; 179cffa8d5SPaul Mackerras u64 config; 1886470930SIngo Molnar char *symbol; 19*74d5b588SJaswinder Singh Rajput char *alias; 2086470930SIngo Molnar }; 2186470930SIngo Molnar 2251e26842SJaswinder Singh Rajput #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 2351e26842SJaswinder Singh Rajput #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x 2486470930SIngo Molnar 2586470930SIngo Molnar static struct event_symbol event_symbols[] = { 26*74d5b588SJaswinder Singh Rajput { CHW(CPU_CYCLES), "cpu-cycles", "cycles" }, 27*74d5b588SJaswinder Singh Rajput { CHW(INSTRUCTIONS), "instructions", "" }, 28*74d5b588SJaswinder Singh Rajput { CHW(CACHE_REFERENCES), "cache-references", "" }, 29*74d5b588SJaswinder Singh Rajput { CHW(CACHE_MISSES), "cache-misses", "" }, 30*74d5b588SJaswinder Singh Rajput { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" }, 31*74d5b588SJaswinder Singh Rajput { CHW(BRANCH_MISSES), "branch-misses", "" }, 32*74d5b588SJaswinder Singh Rajput { CHW(BUS_CYCLES), "bus-cycles", "" }, 3386470930SIngo Molnar 34*74d5b588SJaswinder Singh Rajput { CSW(CPU_CLOCK), "cpu-clock", "" }, 35*74d5b588SJaswinder Singh Rajput { CSW(TASK_CLOCK), "task-clock", "" }, 36*74d5b588SJaswinder Singh Rajput { CSW(PAGE_FAULTS), "page-faults", "" }, 37*74d5b588SJaswinder Singh Rajput { CSW(PAGE_FAULTS), "faults", "" }, 38*74d5b588SJaswinder Singh Rajput { CSW(PAGE_FAULTS_MIN), "minor-faults", "" }, 39*74d5b588SJaswinder Singh Rajput { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, 40*74d5b588SJaswinder Singh Rajput { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, 41*74d5b588SJaswinder Singh Rajput { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, 4286470930SIngo Molnar }; 4386470930SIngo Molnar 4486470930SIngo Molnar #define __PERF_COUNTER_FIELD(config, name) \ 4586470930SIngo Molnar ((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT) 4686470930SIngo Molnar 4786470930SIngo Molnar #define PERF_COUNTER_RAW(config) __PERF_COUNTER_FIELD(config, RAW) 4886470930SIngo Molnar #define PERF_COUNTER_CONFIG(config) __PERF_COUNTER_FIELD(config, CONFIG) 4986470930SIngo Molnar #define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE) 5086470930SIngo Molnar #define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT) 5186470930SIngo Molnar 5286470930SIngo Molnar static char *hw_event_names[] = { 5386470930SIngo Molnar "cycles", 5486470930SIngo Molnar "instructions", 5586470930SIngo Molnar "cache-references", 5686470930SIngo Molnar "cache-misses", 5786470930SIngo Molnar "branches", 5886470930SIngo Molnar "branch-misses", 5986470930SIngo Molnar "bus-cycles", 6086470930SIngo Molnar }; 6186470930SIngo Molnar 6286470930SIngo Molnar static char *sw_event_names[] = { 6344175b6fSIngo Molnar "cpu-clock-msecs", 6444175b6fSIngo Molnar "task-clock-msecs", 6586470930SIngo Molnar "page-faults", 6686470930SIngo Molnar "context-switches", 6786470930SIngo Molnar "CPU-migrations", 6886470930SIngo Molnar "minor-faults", 6986470930SIngo Molnar "major-faults", 7086470930SIngo Molnar }; 7186470930SIngo Molnar 7286470930SIngo Molnar #define MAX_ALIASES 8 7386470930SIngo Molnar 7486470930SIngo Molnar static char *hw_cache [][MAX_ALIASES] = { 75faafec1eSYong Wang { "L1-data" , "l1-d", "l1d" }, 7686470930SIngo Molnar { "L1-instruction" , "l1-i", "l1i" }, 7786470930SIngo Molnar { "L2" , "l2" }, 7886470930SIngo Molnar { "Data-TLB" , "dtlb", "d-tlb" }, 7986470930SIngo Molnar { "Instruction-TLB" , "itlb", "i-tlb" }, 8086470930SIngo Molnar { "Branch" , "bpu" , "btb", "bpc" }, 8186470930SIngo Molnar }; 8286470930SIngo Molnar 8386470930SIngo Molnar static char *hw_cache_op [][MAX_ALIASES] = { 8486470930SIngo Molnar { "Load" , "read" }, 8586470930SIngo Molnar { "Store" , "write" }, 8686470930SIngo Molnar { "Prefetch" , "speculative-read", "speculative-load" }, 8786470930SIngo Molnar }; 8886470930SIngo Molnar 8986470930SIngo Molnar static char *hw_cache_result [][MAX_ALIASES] = { 9086470930SIngo Molnar { "Reference" , "ops", "access" }, 9186470930SIngo Molnar { "Miss" }, 9286470930SIngo Molnar }; 9386470930SIngo Molnar 9486470930SIngo Molnar char *event_name(int counter) 9586470930SIngo Molnar { 969cffa8d5SPaul Mackerras u64 config = attrs[counter].config; 9786470930SIngo Molnar int type = attrs[counter].type; 9886470930SIngo Molnar static char buf[32]; 9986470930SIngo Molnar 10086470930SIngo Molnar if (attrs[counter].type == PERF_TYPE_RAW) { 10186470930SIngo Molnar sprintf(buf, "raw 0x%llx", config); 10286470930SIngo Molnar return buf; 10386470930SIngo Molnar } 10486470930SIngo Molnar 10586470930SIngo Molnar switch (type) { 10686470930SIngo Molnar case PERF_TYPE_HARDWARE: 107f4dbfa8fSPeter Zijlstra if (config < PERF_COUNT_HW_MAX) 10886470930SIngo Molnar return hw_event_names[config]; 10986470930SIngo Molnar return "unknown-hardware"; 11086470930SIngo Molnar 11186470930SIngo Molnar case PERF_TYPE_HW_CACHE: { 1129cffa8d5SPaul Mackerras u8 cache_type, cache_op, cache_result; 11386470930SIngo Molnar static char name[100]; 11486470930SIngo Molnar 11586470930SIngo Molnar cache_type = (config >> 0) & 0xff; 11686470930SIngo Molnar if (cache_type > PERF_COUNT_HW_CACHE_MAX) 11786470930SIngo Molnar return "unknown-ext-hardware-cache-type"; 11886470930SIngo Molnar 11986470930SIngo Molnar cache_op = (config >> 8) & 0xff; 12086470930SIngo Molnar if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX) 12186470930SIngo Molnar return "unknown-ext-hardware-cache-op"; 12286470930SIngo Molnar 12386470930SIngo Molnar cache_result = (config >> 16) & 0xff; 12486470930SIngo Molnar if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX) 12586470930SIngo Molnar return "unknown-ext-hardware-cache-result"; 12686470930SIngo Molnar 12786470930SIngo Molnar sprintf(name, "%s-Cache-%s-%ses", 12886470930SIngo Molnar hw_cache[cache_type][0], 12986470930SIngo Molnar hw_cache_op[cache_op][0], 13086470930SIngo Molnar hw_cache_result[cache_result][0]); 13186470930SIngo Molnar 13286470930SIngo Molnar return name; 13386470930SIngo Molnar } 13486470930SIngo Molnar 13586470930SIngo Molnar case PERF_TYPE_SOFTWARE: 136f4dbfa8fSPeter Zijlstra if (config < PERF_COUNT_SW_MAX) 13786470930SIngo Molnar return sw_event_names[config]; 13886470930SIngo Molnar return "unknown-software"; 13986470930SIngo Molnar 14086470930SIngo Molnar default: 14186470930SIngo Molnar break; 14286470930SIngo Molnar } 14386470930SIngo Molnar 14486470930SIngo Molnar return "unknown"; 14586470930SIngo Molnar } 14686470930SIngo Molnar 14786470930SIngo Molnar static int parse_aliases(const char *str, char *names[][MAX_ALIASES], int size) 14886470930SIngo Molnar { 14986470930SIngo Molnar int i, j; 15086470930SIngo Molnar 15186470930SIngo Molnar for (i = 0; i < size; i++) { 15286470930SIngo Molnar for (j = 0; j < MAX_ALIASES; j++) { 15386470930SIngo Molnar if (!names[i][j]) 15486470930SIngo Molnar break; 15586470930SIngo Molnar if (strcasestr(str, names[i][j])) 15686470930SIngo Molnar return i; 15786470930SIngo Molnar } 15886470930SIngo Molnar } 15986470930SIngo Molnar 1608953645fSIngo Molnar return -1; 16186470930SIngo Molnar } 16286470930SIngo Molnar 16386470930SIngo Molnar static int parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr) 16486470930SIngo Molnar { 1658953645fSIngo Molnar int cache_type = -1, cache_op = 0, cache_result = 0; 16686470930SIngo Molnar 16786470930SIngo Molnar cache_type = parse_aliases(str, hw_cache, PERF_COUNT_HW_CACHE_MAX); 16886470930SIngo Molnar /* 16986470930SIngo Molnar * No fallback - if we cannot get a clear cache type 17086470930SIngo Molnar * then bail out: 17186470930SIngo Molnar */ 17286470930SIngo Molnar if (cache_type == -1) 17386470930SIngo Molnar return -EINVAL; 17486470930SIngo Molnar 17586470930SIngo Molnar cache_op = parse_aliases(str, hw_cache_op, PERF_COUNT_HW_CACHE_OP_MAX); 17686470930SIngo Molnar /* 17786470930SIngo Molnar * Fall back to reads: 17886470930SIngo Molnar */ 1798953645fSIngo Molnar if (cache_op == -1) 1808953645fSIngo Molnar cache_op = PERF_COUNT_HW_CACHE_OP_READ; 18186470930SIngo Molnar 18286470930SIngo Molnar cache_result = parse_aliases(str, hw_cache_result, 18386470930SIngo Molnar PERF_COUNT_HW_CACHE_RESULT_MAX); 18486470930SIngo Molnar /* 18586470930SIngo Molnar * Fall back to accesses: 18686470930SIngo Molnar */ 18786470930SIngo Molnar if (cache_result == -1) 18886470930SIngo Molnar cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS; 18986470930SIngo Molnar 19086470930SIngo Molnar attr->config = cache_type | (cache_op << 8) | (cache_result << 16); 19186470930SIngo Molnar attr->type = PERF_TYPE_HW_CACHE; 19286470930SIngo Molnar 19386470930SIngo Molnar return 0; 19486470930SIngo Molnar } 19586470930SIngo Molnar 196*74d5b588SJaswinder Singh Rajput static int check_events(const char *str, unsigned int i) 197*74d5b588SJaswinder Singh Rajput { 198*74d5b588SJaswinder Singh Rajput if (!strncmp(str, event_symbols[i].symbol, 199*74d5b588SJaswinder Singh Rajput strlen(event_symbols[i].symbol))) 200*74d5b588SJaswinder Singh Rajput return 1; 201*74d5b588SJaswinder Singh Rajput 202*74d5b588SJaswinder Singh Rajput if (strlen(event_symbols[i].alias)) 203*74d5b588SJaswinder Singh Rajput if (!strncmp(str, event_symbols[i].alias, 204*74d5b588SJaswinder Singh Rajput strlen(event_symbols[i].alias))) 205*74d5b588SJaswinder Singh Rajput return 1; 206*74d5b588SJaswinder Singh Rajput return 0; 207*74d5b588SJaswinder Singh Rajput } 208*74d5b588SJaswinder Singh Rajput 20986470930SIngo Molnar /* 21086470930SIngo Molnar * Each event can have multiple symbolic names. 21186470930SIngo Molnar * Symbolic names are (almost) exactly matched. 21286470930SIngo Molnar */ 21386470930SIngo Molnar static int parse_event_symbols(const char *str, struct perf_counter_attr *attr) 21486470930SIngo Molnar { 2159cffa8d5SPaul Mackerras u64 config, id; 21686470930SIngo Molnar int type; 21786470930SIngo Molnar unsigned int i; 21886470930SIngo Molnar const char *sep, *pstr; 21986470930SIngo Molnar 22086470930SIngo Molnar if (str[0] == 'r' && hex2u64(str + 1, &config) > 0) { 22186470930SIngo Molnar attr->type = PERF_TYPE_RAW; 22286470930SIngo Molnar attr->config = config; 22386470930SIngo Molnar 22486470930SIngo Molnar return 0; 22586470930SIngo Molnar } 22686470930SIngo Molnar 22786470930SIngo Molnar pstr = str; 22886470930SIngo Molnar sep = strchr(pstr, ':'); 22986470930SIngo Molnar if (sep) { 23086470930SIngo Molnar type = atoi(pstr); 23186470930SIngo Molnar pstr = sep + 1; 23286470930SIngo Molnar id = atoi(pstr); 23386470930SIngo Molnar sep = strchr(pstr, ':'); 23486470930SIngo Molnar if (sep) { 23586470930SIngo Molnar pstr = sep + 1; 23686470930SIngo Molnar if (strchr(pstr, 'k')) 23786470930SIngo Molnar attr->exclude_user = 1; 23886470930SIngo Molnar if (strchr(pstr, 'u')) 23986470930SIngo Molnar attr->exclude_kernel = 1; 24086470930SIngo Molnar } 24186470930SIngo Molnar attr->type = type; 24286470930SIngo Molnar attr->config = id; 24386470930SIngo Molnar 24486470930SIngo Molnar return 0; 24586470930SIngo Molnar } 24686470930SIngo Molnar 24786470930SIngo Molnar for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { 248*74d5b588SJaswinder Singh Rajput if (check_events(str, i)) { 24986470930SIngo Molnar attr->type = event_symbols[i].type; 25086470930SIngo Molnar attr->config = event_symbols[i].config; 25186470930SIngo Molnar 25286470930SIngo Molnar return 0; 25386470930SIngo Molnar } 25486470930SIngo Molnar } 25586470930SIngo Molnar 25686470930SIngo Molnar return parse_generic_hw_symbols(str, attr); 25786470930SIngo Molnar } 25886470930SIngo Molnar 25986470930SIngo Molnar int parse_events(const struct option *opt, const char *str, int unset) 26086470930SIngo Molnar { 26186470930SIngo Molnar struct perf_counter_attr attr; 26286470930SIngo Molnar int ret; 26386470930SIngo Molnar 26486470930SIngo Molnar memset(&attr, 0, sizeof(attr)); 26586470930SIngo Molnar again: 26686470930SIngo Molnar if (nr_counters == MAX_COUNTERS) 26786470930SIngo Molnar return -1; 26886470930SIngo Molnar 26986470930SIngo Molnar ret = parse_event_symbols(str, &attr); 27086470930SIngo Molnar if (ret < 0) 27186470930SIngo Molnar return ret; 27286470930SIngo Molnar 27386470930SIngo Molnar attrs[nr_counters] = attr; 27486470930SIngo Molnar nr_counters++; 27586470930SIngo Molnar 27686470930SIngo Molnar str = strstr(str, ","); 27786470930SIngo Molnar if (str) { 27886470930SIngo Molnar str++; 27986470930SIngo Molnar goto again; 28086470930SIngo Molnar } 28186470930SIngo Molnar 28286470930SIngo Molnar return 0; 28386470930SIngo Molnar } 28486470930SIngo Molnar 28586470930SIngo Molnar static const char * const event_type_descriptors[] = { 28686470930SIngo Molnar "", 28786470930SIngo Molnar "Hardware event", 28886470930SIngo Molnar "Software event", 28986470930SIngo Molnar "Tracepoint event", 29086470930SIngo Molnar "Hardware cache event", 29186470930SIngo Molnar }; 29286470930SIngo Molnar 29386470930SIngo Molnar /* 29486470930SIngo Molnar * Print the help text for the event symbols: 29586470930SIngo Molnar */ 29686470930SIngo Molnar void print_events(void) 29786470930SIngo Molnar { 29886470930SIngo Molnar struct event_symbol *syms = event_symbols; 29986470930SIngo Molnar unsigned int i, type, prev_type = -1; 300*74d5b588SJaswinder Singh Rajput char name[40]; 30186470930SIngo Molnar 30286470930SIngo Molnar fprintf(stderr, "\n"); 30386470930SIngo Molnar fprintf(stderr, "List of pre-defined events (to be used in -e):\n"); 30486470930SIngo Molnar 30586470930SIngo Molnar for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 30686470930SIngo Molnar type = syms->type + 1; 30786470930SIngo Molnar if (type > ARRAY_SIZE(event_type_descriptors)) 30886470930SIngo Molnar type = 0; 30986470930SIngo Molnar 31086470930SIngo Molnar if (type != prev_type) 31186470930SIngo Molnar fprintf(stderr, "\n"); 31286470930SIngo Molnar 313*74d5b588SJaswinder Singh Rajput if (strlen(syms->alias)) 314*74d5b588SJaswinder Singh Rajput sprintf(name, "%s OR %s", syms->symbol, syms->alias); 315*74d5b588SJaswinder Singh Rajput else 316*74d5b588SJaswinder Singh Rajput strcpy(name, syms->symbol); 317*74d5b588SJaswinder Singh Rajput fprintf(stderr, " %-40s [%s]\n", name, 31886470930SIngo Molnar event_type_descriptors[type]); 31986470930SIngo Molnar 32086470930SIngo Molnar prev_type = type; 32186470930SIngo Molnar } 32286470930SIngo Molnar 32386470930SIngo Molnar fprintf(stderr, "\n"); 324*74d5b588SJaswinder Singh Rajput fprintf(stderr, " %-40s [raw hardware event descriptor]\n", 32586470930SIngo Molnar "rNNN"); 32686470930SIngo Molnar fprintf(stderr, "\n"); 32786470930SIngo Molnar 32886470930SIngo Molnar exit(129); 32986470930SIngo Molnar } 330