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 { 1686470930SIngo Molnar __u8 type; 1786470930SIngo Molnar __u64 config; 1886470930SIngo Molnar char *symbol; 1986470930SIngo Molnar }; 2086470930SIngo Molnar 2186470930SIngo Molnar #define C(x, y) .type = PERF_TYPE_##x, .config = PERF_COUNT_##y 2286470930SIngo Molnar #define CR(x, y) .type = PERF_TYPE_##x, .config = y 2386470930SIngo Molnar 2486470930SIngo Molnar static struct event_symbol event_symbols[] = { 25f4dbfa8fSPeter Zijlstra { C(HARDWARE, HW_CPU_CYCLES), "cpu-cycles", }, 26f4dbfa8fSPeter Zijlstra { C(HARDWARE, HW_CPU_CYCLES), "cycles", }, 27f4dbfa8fSPeter Zijlstra { C(HARDWARE, HW_INSTRUCTIONS), "instructions", }, 28f4dbfa8fSPeter Zijlstra { C(HARDWARE, HW_CACHE_REFERENCES), "cache-references", }, 29f4dbfa8fSPeter Zijlstra { C(HARDWARE, HW_CACHE_MISSES), "cache-misses", }, 30f4dbfa8fSPeter Zijlstra { C(HARDWARE, HW_BRANCH_INSTRUCTIONS),"branch-instructions", }, 31f4dbfa8fSPeter Zijlstra { C(HARDWARE, HW_BRANCH_INSTRUCTIONS),"branches", }, 32f4dbfa8fSPeter Zijlstra { C(HARDWARE, HW_BRANCH_MISSES), "branch-misses", }, 33f4dbfa8fSPeter Zijlstra { C(HARDWARE, HW_BUS_CYCLES), "bus-cycles", }, 3486470930SIngo Molnar 35f4dbfa8fSPeter Zijlstra { C(SOFTWARE, SW_CPU_CLOCK), "cpu-clock", }, 36f4dbfa8fSPeter Zijlstra { C(SOFTWARE, SW_TASK_CLOCK), "task-clock", }, 37f4dbfa8fSPeter Zijlstra { C(SOFTWARE, SW_PAGE_FAULTS), "page-faults", }, 38f4dbfa8fSPeter Zijlstra { C(SOFTWARE, SW_PAGE_FAULTS), "faults", }, 39f4dbfa8fSPeter Zijlstra { C(SOFTWARE, SW_PAGE_FAULTS_MIN), "minor-faults", }, 40f4dbfa8fSPeter Zijlstra { C(SOFTWARE, SW_PAGE_FAULTS_MAJ), "major-faults", }, 41f4dbfa8fSPeter Zijlstra { C(SOFTWARE, SW_CONTEXT_SWITCHES), "context-switches", }, 42f4dbfa8fSPeter Zijlstra { C(SOFTWARE, SW_CONTEXT_SWITCHES), "cs", }, 43f4dbfa8fSPeter Zijlstra { C(SOFTWARE, SW_CPU_MIGRATIONS), "cpu-migrations", }, 44f4dbfa8fSPeter Zijlstra { C(SOFTWARE, SW_CPU_MIGRATIONS), "migrations", }, 4586470930SIngo Molnar }; 4686470930SIngo Molnar 4786470930SIngo Molnar #define __PERF_COUNTER_FIELD(config, name) \ 4886470930SIngo Molnar ((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT) 4986470930SIngo Molnar 5086470930SIngo Molnar #define PERF_COUNTER_RAW(config) __PERF_COUNTER_FIELD(config, RAW) 5186470930SIngo Molnar #define PERF_COUNTER_CONFIG(config) __PERF_COUNTER_FIELD(config, CONFIG) 5286470930SIngo Molnar #define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE) 5386470930SIngo Molnar #define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT) 5486470930SIngo Molnar 5586470930SIngo Molnar static char *hw_event_names[] = { 5686470930SIngo Molnar "cycles", 5786470930SIngo Molnar "instructions", 5886470930SIngo Molnar "cache-references", 5986470930SIngo Molnar "cache-misses", 6086470930SIngo Molnar "branches", 6186470930SIngo Molnar "branch-misses", 6286470930SIngo Molnar "bus-cycles", 6386470930SIngo Molnar }; 6486470930SIngo Molnar 6586470930SIngo Molnar static char *sw_event_names[] = { 6686470930SIngo Molnar "cpu-clock-ticks", 6786470930SIngo Molnar "task-clock-ticks", 6886470930SIngo Molnar "page-faults", 6986470930SIngo Molnar "context-switches", 7086470930SIngo Molnar "CPU-migrations", 7186470930SIngo Molnar "minor-faults", 7286470930SIngo Molnar "major-faults", 7386470930SIngo Molnar }; 7486470930SIngo Molnar 7586470930SIngo Molnar #define MAX_ALIASES 8 7686470930SIngo Molnar 7786470930SIngo Molnar static char *hw_cache [][MAX_ALIASES] = { 78*faafec1eSYong Wang { "L1-data" , "l1-d", "l1d" }, 7986470930SIngo Molnar { "L1-instruction" , "l1-i", "l1i" }, 8086470930SIngo Molnar { "L2" , "l2" }, 8186470930SIngo Molnar { "Data-TLB" , "dtlb", "d-tlb" }, 8286470930SIngo Molnar { "Instruction-TLB" , "itlb", "i-tlb" }, 8386470930SIngo Molnar { "Branch" , "bpu" , "btb", "bpc" }, 8486470930SIngo Molnar }; 8586470930SIngo Molnar 8686470930SIngo Molnar static char *hw_cache_op [][MAX_ALIASES] = { 8786470930SIngo Molnar { "Load" , "read" }, 8886470930SIngo Molnar { "Store" , "write" }, 8986470930SIngo Molnar { "Prefetch" , "speculative-read", "speculative-load" }, 9086470930SIngo Molnar }; 9186470930SIngo Molnar 9286470930SIngo Molnar static char *hw_cache_result [][MAX_ALIASES] = { 9386470930SIngo Molnar { "Reference" , "ops", "access" }, 9486470930SIngo Molnar { "Miss" }, 9586470930SIngo Molnar }; 9686470930SIngo Molnar 9786470930SIngo Molnar char *event_name(int counter) 9886470930SIngo Molnar { 9986470930SIngo Molnar __u64 config = attrs[counter].config; 10086470930SIngo Molnar int type = attrs[counter].type; 10186470930SIngo Molnar static char buf[32]; 10286470930SIngo Molnar 10386470930SIngo Molnar if (attrs[counter].type == PERF_TYPE_RAW) { 10486470930SIngo Molnar sprintf(buf, "raw 0x%llx", config); 10586470930SIngo Molnar return buf; 10686470930SIngo Molnar } 10786470930SIngo Molnar 10886470930SIngo Molnar switch (type) { 10986470930SIngo Molnar case PERF_TYPE_HARDWARE: 110f4dbfa8fSPeter Zijlstra if (config < PERF_COUNT_HW_MAX) 11186470930SIngo Molnar return hw_event_names[config]; 11286470930SIngo Molnar return "unknown-hardware"; 11386470930SIngo Molnar 11486470930SIngo Molnar case PERF_TYPE_HW_CACHE: { 11586470930SIngo Molnar __u8 cache_type, cache_op, cache_result; 11686470930SIngo Molnar static char name[100]; 11786470930SIngo Molnar 11886470930SIngo Molnar cache_type = (config >> 0) & 0xff; 11986470930SIngo Molnar if (cache_type > PERF_COUNT_HW_CACHE_MAX) 12086470930SIngo Molnar return "unknown-ext-hardware-cache-type"; 12186470930SIngo Molnar 12286470930SIngo Molnar cache_op = (config >> 8) & 0xff; 12386470930SIngo Molnar if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX) 12486470930SIngo Molnar return "unknown-ext-hardware-cache-op"; 12586470930SIngo Molnar 12686470930SIngo Molnar cache_result = (config >> 16) & 0xff; 12786470930SIngo Molnar if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX) 12886470930SIngo Molnar return "unknown-ext-hardware-cache-result"; 12986470930SIngo Molnar 13086470930SIngo Molnar sprintf(name, "%s-Cache-%s-%ses", 13186470930SIngo Molnar hw_cache[cache_type][0], 13286470930SIngo Molnar hw_cache_op[cache_op][0], 13386470930SIngo Molnar hw_cache_result[cache_result][0]); 13486470930SIngo Molnar 13586470930SIngo Molnar return name; 13686470930SIngo Molnar } 13786470930SIngo Molnar 13886470930SIngo Molnar case PERF_TYPE_SOFTWARE: 139f4dbfa8fSPeter Zijlstra if (config < PERF_COUNT_SW_MAX) 14086470930SIngo Molnar return sw_event_names[config]; 14186470930SIngo Molnar return "unknown-software"; 14286470930SIngo Molnar 14386470930SIngo Molnar default: 14486470930SIngo Molnar break; 14586470930SIngo Molnar } 14686470930SIngo Molnar 14786470930SIngo Molnar return "unknown"; 14886470930SIngo Molnar } 14986470930SIngo Molnar 15086470930SIngo Molnar static int parse_aliases(const char *str, char *names[][MAX_ALIASES], int size) 15186470930SIngo Molnar { 15286470930SIngo Molnar int i, j; 15386470930SIngo Molnar 15486470930SIngo Molnar for (i = 0; i < size; i++) { 15586470930SIngo Molnar for (j = 0; j < MAX_ALIASES; j++) { 15686470930SIngo Molnar if (!names[i][j]) 15786470930SIngo Molnar break; 15886470930SIngo Molnar if (strcasestr(str, names[i][j])) 15986470930SIngo Molnar return i; 16086470930SIngo Molnar } 16186470930SIngo Molnar } 16286470930SIngo Molnar 1638953645fSIngo Molnar return -1; 16486470930SIngo Molnar } 16586470930SIngo Molnar 16686470930SIngo Molnar static int parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr) 16786470930SIngo Molnar { 1688953645fSIngo Molnar int cache_type = -1, cache_op = 0, cache_result = 0; 16986470930SIngo Molnar 17086470930SIngo Molnar cache_type = parse_aliases(str, hw_cache, PERF_COUNT_HW_CACHE_MAX); 17186470930SIngo Molnar /* 17286470930SIngo Molnar * No fallback - if we cannot get a clear cache type 17386470930SIngo Molnar * then bail out: 17486470930SIngo Molnar */ 17586470930SIngo Molnar if (cache_type == -1) 17686470930SIngo Molnar return -EINVAL; 17786470930SIngo Molnar 17886470930SIngo Molnar cache_op = parse_aliases(str, hw_cache_op, PERF_COUNT_HW_CACHE_OP_MAX); 17986470930SIngo Molnar /* 18086470930SIngo Molnar * Fall back to reads: 18186470930SIngo Molnar */ 1828953645fSIngo Molnar if (cache_op == -1) 1838953645fSIngo Molnar cache_op = PERF_COUNT_HW_CACHE_OP_READ; 18486470930SIngo Molnar 18586470930SIngo Molnar cache_result = parse_aliases(str, hw_cache_result, 18686470930SIngo Molnar PERF_COUNT_HW_CACHE_RESULT_MAX); 18786470930SIngo Molnar /* 18886470930SIngo Molnar * Fall back to accesses: 18986470930SIngo Molnar */ 19086470930SIngo Molnar if (cache_result == -1) 19186470930SIngo Molnar cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS; 19286470930SIngo Molnar 19386470930SIngo Molnar attr->config = cache_type | (cache_op << 8) | (cache_result << 16); 19486470930SIngo Molnar attr->type = PERF_TYPE_HW_CACHE; 19586470930SIngo Molnar 19686470930SIngo Molnar return 0; 19786470930SIngo Molnar } 19886470930SIngo Molnar 19986470930SIngo Molnar /* 20086470930SIngo Molnar * Each event can have multiple symbolic names. 20186470930SIngo Molnar * Symbolic names are (almost) exactly matched. 20286470930SIngo Molnar */ 20386470930SIngo Molnar static int parse_event_symbols(const char *str, struct perf_counter_attr *attr) 20486470930SIngo Molnar { 20586470930SIngo Molnar __u64 config, id; 20686470930SIngo Molnar int type; 20786470930SIngo Molnar unsigned int i; 20886470930SIngo Molnar const char *sep, *pstr; 20986470930SIngo Molnar 21086470930SIngo Molnar if (str[0] == 'r' && hex2u64(str + 1, &config) > 0) { 21186470930SIngo Molnar attr->type = PERF_TYPE_RAW; 21286470930SIngo Molnar attr->config = config; 21386470930SIngo Molnar 21486470930SIngo Molnar return 0; 21586470930SIngo Molnar } 21686470930SIngo Molnar 21786470930SIngo Molnar pstr = str; 21886470930SIngo Molnar sep = strchr(pstr, ':'); 21986470930SIngo Molnar if (sep) { 22086470930SIngo Molnar type = atoi(pstr); 22186470930SIngo Molnar pstr = sep + 1; 22286470930SIngo Molnar id = atoi(pstr); 22386470930SIngo Molnar sep = strchr(pstr, ':'); 22486470930SIngo Molnar if (sep) { 22586470930SIngo Molnar pstr = sep + 1; 22686470930SIngo Molnar if (strchr(pstr, 'k')) 22786470930SIngo Molnar attr->exclude_user = 1; 22886470930SIngo Molnar if (strchr(pstr, 'u')) 22986470930SIngo Molnar attr->exclude_kernel = 1; 23086470930SIngo Molnar } 23186470930SIngo Molnar attr->type = type; 23286470930SIngo Molnar attr->config = id; 23386470930SIngo Molnar 23486470930SIngo Molnar return 0; 23586470930SIngo Molnar } 23686470930SIngo Molnar 23786470930SIngo Molnar for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { 23886470930SIngo Molnar if (!strncmp(str, event_symbols[i].symbol, 23986470930SIngo Molnar strlen(event_symbols[i].symbol))) { 24086470930SIngo Molnar 24186470930SIngo Molnar attr->type = event_symbols[i].type; 24286470930SIngo Molnar attr->config = event_symbols[i].config; 24386470930SIngo Molnar 24486470930SIngo Molnar return 0; 24586470930SIngo Molnar } 24686470930SIngo Molnar } 24786470930SIngo Molnar 24886470930SIngo Molnar return parse_generic_hw_symbols(str, attr); 24986470930SIngo Molnar } 25086470930SIngo Molnar 25186470930SIngo Molnar int parse_events(const struct option *opt, const char *str, int unset) 25286470930SIngo Molnar { 25386470930SIngo Molnar struct perf_counter_attr attr; 25486470930SIngo Molnar int ret; 25586470930SIngo Molnar 25686470930SIngo Molnar memset(&attr, 0, sizeof(attr)); 25786470930SIngo Molnar again: 25886470930SIngo Molnar if (nr_counters == MAX_COUNTERS) 25986470930SIngo Molnar return -1; 26086470930SIngo Molnar 26186470930SIngo Molnar ret = parse_event_symbols(str, &attr); 26286470930SIngo Molnar if (ret < 0) 26386470930SIngo Molnar return ret; 26486470930SIngo Molnar 26586470930SIngo Molnar attrs[nr_counters] = attr; 26686470930SIngo Molnar nr_counters++; 26786470930SIngo Molnar 26886470930SIngo Molnar str = strstr(str, ","); 26986470930SIngo Molnar if (str) { 27086470930SIngo Molnar str++; 27186470930SIngo Molnar goto again; 27286470930SIngo Molnar } 27386470930SIngo Molnar 27486470930SIngo Molnar return 0; 27586470930SIngo Molnar } 27686470930SIngo Molnar 27786470930SIngo Molnar static const char * const event_type_descriptors[] = { 27886470930SIngo Molnar "", 27986470930SIngo Molnar "Hardware event", 28086470930SIngo Molnar "Software event", 28186470930SIngo Molnar "Tracepoint event", 28286470930SIngo Molnar "Hardware cache event", 28386470930SIngo Molnar }; 28486470930SIngo Molnar 28586470930SIngo Molnar /* 28686470930SIngo Molnar * Print the help text for the event symbols: 28786470930SIngo Molnar */ 28886470930SIngo Molnar void print_events(void) 28986470930SIngo Molnar { 29086470930SIngo Molnar struct event_symbol *syms = event_symbols; 29186470930SIngo Molnar unsigned int i, type, prev_type = -1; 29286470930SIngo Molnar 29386470930SIngo Molnar fprintf(stderr, "\n"); 29486470930SIngo Molnar fprintf(stderr, "List of pre-defined events (to be used in -e):\n"); 29586470930SIngo Molnar 29686470930SIngo Molnar for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 29786470930SIngo Molnar type = syms->type + 1; 29886470930SIngo Molnar if (type > ARRAY_SIZE(event_type_descriptors)) 29986470930SIngo Molnar type = 0; 30086470930SIngo Molnar 30186470930SIngo Molnar if (type != prev_type) 30286470930SIngo Molnar fprintf(stderr, "\n"); 30386470930SIngo Molnar 30486470930SIngo Molnar fprintf(stderr, " %-30s [%s]\n", syms->symbol, 30586470930SIngo Molnar event_type_descriptors[type]); 30686470930SIngo Molnar 30786470930SIngo Molnar prev_type = type; 30886470930SIngo Molnar } 30986470930SIngo Molnar 31086470930SIngo Molnar fprintf(stderr, "\n"); 31186470930SIngo Molnar fprintf(stderr, " %-30s [raw hardware event descriptor]\n", 31286470930SIngo Molnar "rNNN"); 31386470930SIngo Molnar fprintf(stderr, "\n"); 31486470930SIngo Molnar 31586470930SIngo Molnar exit(129); 31686470930SIngo Molnar } 317