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; 1974d5b588SJaswinder 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[] = { 2674d5b588SJaswinder Singh Rajput { CHW(CPU_CYCLES), "cpu-cycles", "cycles" }, 2774d5b588SJaswinder Singh Rajput { CHW(INSTRUCTIONS), "instructions", "" }, 2874d5b588SJaswinder Singh Rajput { CHW(CACHE_REFERENCES), "cache-references", "" }, 2974d5b588SJaswinder Singh Rajput { CHW(CACHE_MISSES), "cache-misses", "" }, 3074d5b588SJaswinder Singh Rajput { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" }, 3174d5b588SJaswinder Singh Rajput { CHW(BRANCH_MISSES), "branch-misses", "" }, 3274d5b588SJaswinder Singh Rajput { CHW(BUS_CYCLES), "bus-cycles", "" }, 3386470930SIngo Molnar 3474d5b588SJaswinder Singh Rajput { CSW(CPU_CLOCK), "cpu-clock", "" }, 3574d5b588SJaswinder Singh Rajput { CSW(TASK_CLOCK), "task-clock", "" }, 36c0c22dbfSJaswinder Singh Rajput { CSW(PAGE_FAULTS), "page-faults", "faults" }, 3774d5b588SJaswinder Singh Rajput { CSW(PAGE_FAULTS_MIN), "minor-faults", "" }, 3874d5b588SJaswinder Singh Rajput { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, 3974d5b588SJaswinder Singh Rajput { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, 4074d5b588SJaswinder Singh Rajput { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, 4186470930SIngo Molnar }; 4286470930SIngo Molnar 4386470930SIngo Molnar #define __PERF_COUNTER_FIELD(config, name) \ 4486470930SIngo Molnar ((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT) 4586470930SIngo Molnar 4686470930SIngo Molnar #define PERF_COUNTER_RAW(config) __PERF_COUNTER_FIELD(config, RAW) 4786470930SIngo Molnar #define PERF_COUNTER_CONFIG(config) __PERF_COUNTER_FIELD(config, CONFIG) 4886470930SIngo Molnar #define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE) 4986470930SIngo Molnar #define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT) 5086470930SIngo Molnar 5186470930SIngo Molnar static char *hw_event_names[] = { 5286470930SIngo Molnar "cycles", 5386470930SIngo Molnar "instructions", 5486470930SIngo Molnar "cache-references", 5586470930SIngo Molnar "cache-misses", 5686470930SIngo Molnar "branches", 5786470930SIngo Molnar "branch-misses", 5886470930SIngo Molnar "bus-cycles", 5986470930SIngo Molnar }; 6086470930SIngo Molnar 6186470930SIngo Molnar static char *sw_event_names[] = { 6244175b6fSIngo Molnar "cpu-clock-msecs", 6344175b6fSIngo Molnar "task-clock-msecs", 6486470930SIngo Molnar "page-faults", 6586470930SIngo Molnar "context-switches", 6686470930SIngo Molnar "CPU-migrations", 6786470930SIngo Molnar "minor-faults", 6886470930SIngo Molnar "major-faults", 6986470930SIngo Molnar }; 7086470930SIngo Molnar 7186470930SIngo Molnar #define MAX_ALIASES 8 7286470930SIngo Molnar 7386470930SIngo Molnar static char *hw_cache[][MAX_ALIASES] = { 744418351fSJaswinder Singh Rajput { "L1-d$", "l1-d", "l1d", "L1-data", }, 754418351fSJaswinder Singh Rajput { "L1-i$", "l1-i", "l1i", "L1-instruction", }, 76e5c59547SJaswinder Singh Rajput { "LLC", "L2" }, 77e5c59547SJaswinder Singh Rajput { "dTLB", "d-tlb", "Data-TLB", }, 78e5c59547SJaswinder Singh Rajput { "iTLB", "i-tlb", "Instruction-TLB", }, 79e5c59547SJaswinder Singh Rajput { "branch", "branches", "bpu", "btb", "bpc", }, 8086470930SIngo Molnar }; 8186470930SIngo Molnar 8286470930SIngo Molnar static char *hw_cache_op[][MAX_ALIASES] = { 83e5c59547SJaswinder Singh Rajput { "load", "loads", "read", }, 84e5c59547SJaswinder Singh Rajput { "store", "stores", "write", }, 85e5c59547SJaswinder Singh Rajput { "prefetch", "prefetches", "speculative-read", "speculative-load", }, 8686470930SIngo Molnar }; 8786470930SIngo Molnar 8886470930SIngo Molnar static char *hw_cache_result[][MAX_ALIASES] = { 89e5c59547SJaswinder Singh Rajput { "refs", "Reference", "ops", "access", }, 90e5c59547SJaswinder Singh Rajput { "misses", "miss", }, 9186470930SIngo Molnar }; 9286470930SIngo Molnar 9306813f6cSJaswinder Singh Rajput #define C(x) PERF_COUNT_HW_CACHE_##x 9406813f6cSJaswinder Singh Rajput #define CACHE_READ (1 << C(OP_READ)) 9506813f6cSJaswinder Singh Rajput #define CACHE_WRITE (1 << C(OP_WRITE)) 9606813f6cSJaswinder Singh Rajput #define CACHE_PREFETCH (1 << C(OP_PREFETCH)) 9706813f6cSJaswinder Singh Rajput #define COP(x) (1 << x) 9806813f6cSJaswinder Singh Rajput 9906813f6cSJaswinder Singh Rajput /* 10006813f6cSJaswinder Singh Rajput * cache operartion stat 10106813f6cSJaswinder Singh Rajput * L1I : Read and prefetch only 10206813f6cSJaswinder Singh Rajput * ITLB and BPU : Read-only 10306813f6cSJaswinder Singh Rajput */ 10406813f6cSJaswinder Singh Rajput static unsigned long hw_cache_stat[C(MAX)] = { 10506813f6cSJaswinder Singh Rajput [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 10606813f6cSJaswinder Singh Rajput [C(L1I)] = (CACHE_READ | CACHE_PREFETCH), 10706813f6cSJaswinder Singh Rajput [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 10806813f6cSJaswinder Singh Rajput [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 10906813f6cSJaswinder Singh Rajput [C(ITLB)] = (CACHE_READ), 11006813f6cSJaswinder Singh Rajput [C(BPU)] = (CACHE_READ), 11106813f6cSJaswinder Singh Rajput }; 11206813f6cSJaswinder Singh Rajput 11306813f6cSJaswinder Singh Rajput static int is_cache_op_valid(u8 cache_type, u8 cache_op) 11406813f6cSJaswinder Singh Rajput { 11506813f6cSJaswinder Singh Rajput if (hw_cache_stat[cache_type] & COP(cache_op)) 11606813f6cSJaswinder Singh Rajput return 1; /* valid */ 11706813f6cSJaswinder Singh Rajput else 11806813f6cSJaswinder Singh Rajput return 0; /* invalid */ 11906813f6cSJaswinder Singh Rajput } 12006813f6cSJaswinder Singh Rajput 121e5c59547SJaswinder Singh Rajput static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result) 122e5c59547SJaswinder Singh Rajput { 123e5c59547SJaswinder Singh Rajput static char name[50]; 124e5c59547SJaswinder Singh Rajput 125e5c59547SJaswinder Singh Rajput if (cache_result) { 126e5c59547SJaswinder Singh Rajput sprintf(name, "%s-%s-%s", hw_cache[cache_type][0], 127e5c59547SJaswinder Singh Rajput hw_cache_op[cache_op][0], 128e5c59547SJaswinder Singh Rajput hw_cache_result[cache_result][0]); 129e5c59547SJaswinder Singh Rajput } else { 130e5c59547SJaswinder Singh Rajput sprintf(name, "%s-%s", hw_cache[cache_type][0], 131e5c59547SJaswinder Singh Rajput hw_cache_op[cache_op][1]); 132e5c59547SJaswinder Singh Rajput } 133e5c59547SJaswinder Singh Rajput 134e5c59547SJaswinder Singh Rajput return name; 135e5c59547SJaswinder Singh Rajput } 136e5c59547SJaswinder Singh Rajput 13786470930SIngo Molnar char *event_name(int counter) 13886470930SIngo Molnar { 1399cffa8d5SPaul Mackerras u64 config = attrs[counter].config; 14086470930SIngo Molnar int type = attrs[counter].type; 14186470930SIngo Molnar static char buf[32]; 14286470930SIngo Molnar 14386470930SIngo Molnar if (attrs[counter].type == PERF_TYPE_RAW) { 14486470930SIngo Molnar sprintf(buf, "raw 0x%llx", config); 14586470930SIngo Molnar return buf; 14686470930SIngo Molnar } 14786470930SIngo Molnar 14886470930SIngo Molnar switch (type) { 14986470930SIngo Molnar case PERF_TYPE_HARDWARE: 150f4dbfa8fSPeter Zijlstra if (config < PERF_COUNT_HW_MAX) 15186470930SIngo Molnar return hw_event_names[config]; 15286470930SIngo Molnar return "unknown-hardware"; 15386470930SIngo Molnar 15486470930SIngo Molnar case PERF_TYPE_HW_CACHE: { 1559cffa8d5SPaul Mackerras u8 cache_type, cache_op, cache_result; 15686470930SIngo Molnar 15786470930SIngo Molnar cache_type = (config >> 0) & 0xff; 15886470930SIngo Molnar if (cache_type > PERF_COUNT_HW_CACHE_MAX) 15986470930SIngo Molnar return "unknown-ext-hardware-cache-type"; 16086470930SIngo Molnar 16186470930SIngo Molnar cache_op = (config >> 8) & 0xff; 16286470930SIngo Molnar if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX) 16386470930SIngo Molnar return "unknown-ext-hardware-cache-op"; 16486470930SIngo Molnar 16586470930SIngo Molnar cache_result = (config >> 16) & 0xff; 16686470930SIngo Molnar if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX) 16786470930SIngo Molnar return "unknown-ext-hardware-cache-result"; 16886470930SIngo Molnar 16906813f6cSJaswinder Singh Rajput if (!is_cache_op_valid(cache_type, cache_op)) 17006813f6cSJaswinder Singh Rajput return "invalid-cache"; 17186470930SIngo Molnar 172e5c59547SJaswinder Singh Rajput return event_cache_name(cache_type, cache_op, cache_result); 17386470930SIngo Molnar } 17486470930SIngo Molnar 17586470930SIngo Molnar case PERF_TYPE_SOFTWARE: 176f4dbfa8fSPeter Zijlstra if (config < PERF_COUNT_SW_MAX) 17786470930SIngo Molnar return sw_event_names[config]; 17886470930SIngo Molnar return "unknown-software"; 17986470930SIngo Molnar 18086470930SIngo Molnar default: 18186470930SIngo Molnar break; 18286470930SIngo Molnar } 18386470930SIngo Molnar 18486470930SIngo Molnar return "unknown"; 18586470930SIngo Molnar } 18686470930SIngo Molnar 18761c45981SPaul Mackerras static int parse_aliases(const char **str, char *names[][MAX_ALIASES], int size) 18886470930SIngo Molnar { 18986470930SIngo Molnar int i, j; 19061c45981SPaul Mackerras int n, longest = -1; 19186470930SIngo Molnar 19286470930SIngo Molnar for (i = 0; i < size; i++) { 19361c45981SPaul Mackerras for (j = 0; j < MAX_ALIASES && names[i][j]; j++) { 19461c45981SPaul Mackerras n = strlen(names[i][j]); 19561c45981SPaul Mackerras if (n > longest && !strncasecmp(*str, names[i][j], n)) 19661c45981SPaul Mackerras longest = n; 19761c45981SPaul Mackerras } 19861c45981SPaul Mackerras if (longest > 0) { 19961c45981SPaul Mackerras *str += longest; 20086470930SIngo Molnar return i; 20186470930SIngo Molnar } 20286470930SIngo Molnar } 20386470930SIngo Molnar 2048953645fSIngo Molnar return -1; 20586470930SIngo Molnar } 20686470930SIngo Molnar 207c0c22dbfSJaswinder Singh Rajput static int 20861c45981SPaul Mackerras parse_generic_hw_event(const char **str, struct perf_counter_attr *attr) 20986470930SIngo Molnar { 21061c45981SPaul Mackerras const char *s = *str; 21161c45981SPaul Mackerras int cache_type = -1, cache_op = -1, cache_result = -1; 21286470930SIngo Molnar 21361c45981SPaul Mackerras cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX); 21486470930SIngo Molnar /* 21586470930SIngo Molnar * No fallback - if we cannot get a clear cache type 21686470930SIngo Molnar * then bail out: 21786470930SIngo Molnar */ 21886470930SIngo Molnar if (cache_type == -1) 21961c45981SPaul Mackerras return 0; 22086470930SIngo Molnar 22161c45981SPaul Mackerras while ((cache_op == -1 || cache_result == -1) && *s == '-') { 22261c45981SPaul Mackerras ++s; 22361c45981SPaul Mackerras 22461c45981SPaul Mackerras if (cache_op == -1) { 22561c45981SPaul Mackerras cache_op = parse_aliases(&s, hw_cache_op, 22661c45981SPaul Mackerras PERF_COUNT_HW_CACHE_OP_MAX); 22761c45981SPaul Mackerras if (cache_op >= 0) { 22861c45981SPaul Mackerras if (!is_cache_op_valid(cache_type, cache_op)) 22961c45981SPaul Mackerras return 0; 23061c45981SPaul Mackerras continue; 23161c45981SPaul Mackerras } 23261c45981SPaul Mackerras } 23361c45981SPaul Mackerras 23461c45981SPaul Mackerras if (cache_result == -1) { 23561c45981SPaul Mackerras cache_result = parse_aliases(&s, hw_cache_result, 23661c45981SPaul Mackerras PERF_COUNT_HW_CACHE_RESULT_MAX); 23761c45981SPaul Mackerras if (cache_result >= 0) 23861c45981SPaul Mackerras continue; 23961c45981SPaul Mackerras } 24061c45981SPaul Mackerras 24161c45981SPaul Mackerras /* 24261c45981SPaul Mackerras * Can't parse this as a cache op or result, so back up 24361c45981SPaul Mackerras * to the '-'. 24461c45981SPaul Mackerras */ 24561c45981SPaul Mackerras --s; 24661c45981SPaul Mackerras break; 24761c45981SPaul Mackerras } 24861c45981SPaul Mackerras 24986470930SIngo Molnar /* 25086470930SIngo Molnar * Fall back to reads: 25186470930SIngo Molnar */ 2528953645fSIngo Molnar if (cache_op == -1) 2538953645fSIngo Molnar cache_op = PERF_COUNT_HW_CACHE_OP_READ; 25486470930SIngo Molnar 25586470930SIngo Molnar /* 25686470930SIngo Molnar * Fall back to accesses: 25786470930SIngo Molnar */ 25886470930SIngo Molnar if (cache_result == -1) 25986470930SIngo Molnar cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS; 26086470930SIngo Molnar 26186470930SIngo Molnar attr->config = cache_type | (cache_op << 8) | (cache_result << 16); 26286470930SIngo Molnar attr->type = PERF_TYPE_HW_CACHE; 26386470930SIngo Molnar 26461c45981SPaul Mackerras *str = s; 26561c45981SPaul Mackerras return 1; 26686470930SIngo Molnar } 26786470930SIngo Molnar 26874d5b588SJaswinder Singh Rajput static int check_events(const char *str, unsigned int i) 26974d5b588SJaswinder Singh Rajput { 27061c45981SPaul Mackerras int n; 27174d5b588SJaswinder Singh Rajput 27261c45981SPaul Mackerras n = strlen(event_symbols[i].symbol); 27361c45981SPaul Mackerras if (!strncmp(str, event_symbols[i].symbol, n)) 27461c45981SPaul Mackerras return n; 27561c45981SPaul Mackerras 27661c45981SPaul Mackerras n = strlen(event_symbols[i].alias); 27761c45981SPaul Mackerras if (n) 27861c45981SPaul Mackerras if (!strncmp(str, event_symbols[i].alias, n)) 27961c45981SPaul Mackerras return n; 28061c45981SPaul Mackerras return 0; 28161c45981SPaul Mackerras } 28261c45981SPaul Mackerras 28361c45981SPaul Mackerras static int 28461c45981SPaul Mackerras parse_symbolic_event(const char **strp, struct perf_counter_attr *attr) 28561c45981SPaul Mackerras { 28661c45981SPaul Mackerras const char *str = *strp; 28761c45981SPaul Mackerras unsigned int i; 28861c45981SPaul Mackerras int n; 28961c45981SPaul Mackerras 29061c45981SPaul Mackerras for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { 29161c45981SPaul Mackerras n = check_events(str, i); 29261c45981SPaul Mackerras if (n > 0) { 29361c45981SPaul Mackerras attr->type = event_symbols[i].type; 29461c45981SPaul Mackerras attr->config = event_symbols[i].config; 29561c45981SPaul Mackerras *strp = str + n; 29674d5b588SJaswinder Singh Rajput return 1; 29761c45981SPaul Mackerras } 29861c45981SPaul Mackerras } 29961c45981SPaul Mackerras return 0; 30061c45981SPaul Mackerras } 30161c45981SPaul Mackerras 30261c45981SPaul Mackerras static int parse_raw_event(const char **strp, struct perf_counter_attr *attr) 30361c45981SPaul Mackerras { 30461c45981SPaul Mackerras const char *str = *strp; 30561c45981SPaul Mackerras u64 config; 30661c45981SPaul Mackerras int n; 30761c45981SPaul Mackerras 30861c45981SPaul Mackerras if (*str != 'r') 30961c45981SPaul Mackerras return 0; 31061c45981SPaul Mackerras n = hex2u64(str + 1, &config); 31161c45981SPaul Mackerras if (n > 0) { 31261c45981SPaul Mackerras *strp = str + n + 1; 31361c45981SPaul Mackerras attr->type = PERF_TYPE_RAW; 31461c45981SPaul Mackerras attr->config = config; 31561c45981SPaul Mackerras return 1; 31661c45981SPaul Mackerras } 31761c45981SPaul Mackerras return 0; 31861c45981SPaul Mackerras } 31961c45981SPaul Mackerras 32061c45981SPaul Mackerras static int 32161c45981SPaul Mackerras parse_numeric_event(const char **strp, struct perf_counter_attr *attr) 32261c45981SPaul Mackerras { 32361c45981SPaul Mackerras const char *str = *strp; 32461c45981SPaul Mackerras char *endp; 32561c45981SPaul Mackerras unsigned long type; 32661c45981SPaul Mackerras u64 config; 32761c45981SPaul Mackerras 32861c45981SPaul Mackerras type = strtoul(str, &endp, 0); 32961c45981SPaul Mackerras if (endp > str && type < PERF_TYPE_MAX && *endp == ':') { 33061c45981SPaul Mackerras str = endp + 1; 33161c45981SPaul Mackerras config = strtoul(str, &endp, 0); 33261c45981SPaul Mackerras if (endp > str) { 33361c45981SPaul Mackerras attr->type = type; 33461c45981SPaul Mackerras attr->config = config; 33561c45981SPaul Mackerras *strp = endp; 33661c45981SPaul Mackerras return 1; 33761c45981SPaul Mackerras } 33861c45981SPaul Mackerras } 33961c45981SPaul Mackerras return 0; 34061c45981SPaul Mackerras } 34161c45981SPaul Mackerras 34261c45981SPaul Mackerras static int 34361c45981SPaul Mackerras parse_event_modifier(const char **strp, struct perf_counter_attr *attr) 34461c45981SPaul Mackerras { 34561c45981SPaul Mackerras const char *str = *strp; 34661c45981SPaul Mackerras int eu = 1, ek = 1, eh = 1; 34761c45981SPaul Mackerras 34861c45981SPaul Mackerras if (*str++ != ':') 34961c45981SPaul Mackerras return 0; 35061c45981SPaul Mackerras while (*str) { 35161c45981SPaul Mackerras if (*str == 'u') 35261c45981SPaul Mackerras eu = 0; 35361c45981SPaul Mackerras else if (*str == 'k') 35461c45981SPaul Mackerras ek = 0; 35561c45981SPaul Mackerras else if (*str == 'h') 35661c45981SPaul Mackerras eh = 0; 35761c45981SPaul Mackerras else 35861c45981SPaul Mackerras break; 35961c45981SPaul Mackerras ++str; 36061c45981SPaul Mackerras } 36161c45981SPaul Mackerras if (str >= *strp + 2) { 36261c45981SPaul Mackerras *strp = str; 36361c45981SPaul Mackerras attr->exclude_user = eu; 36461c45981SPaul Mackerras attr->exclude_kernel = ek; 36561c45981SPaul Mackerras attr->exclude_hv = eh; 36661c45981SPaul Mackerras return 1; 36761c45981SPaul Mackerras } 36874d5b588SJaswinder Singh Rajput return 0; 36974d5b588SJaswinder Singh Rajput } 37074d5b588SJaswinder Singh Rajput 37186470930SIngo Molnar /* 37286470930SIngo Molnar * Each event can have multiple symbolic names. 37386470930SIngo Molnar * Symbolic names are (almost) exactly matched. 37486470930SIngo Molnar */ 37561c45981SPaul Mackerras static int parse_event_symbols(const char **str, struct perf_counter_attr *attr) 37686470930SIngo Molnar { 37761c45981SPaul Mackerras if (!(parse_raw_event(str, attr) || 37861c45981SPaul Mackerras parse_numeric_event(str, attr) || 37961c45981SPaul Mackerras parse_symbolic_event(str, attr) || 38061c45981SPaul Mackerras parse_generic_hw_event(str, attr))) 38186470930SIngo Molnar return 0; 38286470930SIngo Molnar 38361c45981SPaul Mackerras parse_event_modifier(str, attr); 38486470930SIngo Molnar 38561c45981SPaul Mackerras return 1; 38686470930SIngo Molnar } 38786470930SIngo Molnar 388*f37a291cSIngo Molnar int parse_events(const struct option *opt __used, const char *str, int unset __used) 38986470930SIngo Molnar { 39086470930SIngo Molnar struct perf_counter_attr attr; 39186470930SIngo Molnar 39261c45981SPaul Mackerras for (;;) { 39386470930SIngo Molnar if (nr_counters == MAX_COUNTERS) 39486470930SIngo Molnar return -1; 39586470930SIngo Molnar 39661c45981SPaul Mackerras memset(&attr, 0, sizeof(attr)); 39761c45981SPaul Mackerras if (!parse_event_symbols(&str, &attr)) 39861c45981SPaul Mackerras return -1; 39961c45981SPaul Mackerras 40061c45981SPaul Mackerras if (!(*str == 0 || *str == ',' || isspace(*str))) 40161c45981SPaul Mackerras return -1; 40286470930SIngo Molnar 40386470930SIngo Molnar attrs[nr_counters] = attr; 40486470930SIngo Molnar nr_counters++; 40586470930SIngo Molnar 40661c45981SPaul Mackerras if (*str == 0) 40761c45981SPaul Mackerras break; 40861c45981SPaul Mackerras if (*str == ',') 40961c45981SPaul Mackerras ++str; 41061c45981SPaul Mackerras while (isspace(*str)) 41161c45981SPaul Mackerras ++str; 41286470930SIngo Molnar } 41386470930SIngo Molnar 41486470930SIngo Molnar return 0; 41586470930SIngo Molnar } 41686470930SIngo Molnar 41786470930SIngo Molnar static const char * const event_type_descriptors[] = { 41886470930SIngo Molnar "", 41986470930SIngo Molnar "Hardware event", 42086470930SIngo Molnar "Software event", 42186470930SIngo Molnar "Tracepoint event", 42286470930SIngo Molnar "Hardware cache event", 42386470930SIngo Molnar }; 42486470930SIngo Molnar 42586470930SIngo Molnar /* 42686470930SIngo Molnar * Print the help text for the event symbols: 42786470930SIngo Molnar */ 42886470930SIngo Molnar void print_events(void) 42986470930SIngo Molnar { 43086470930SIngo Molnar struct event_symbol *syms = event_symbols; 43186470930SIngo Molnar unsigned int i, type, prev_type = -1; 43274d5b588SJaswinder Singh Rajput char name[40]; 43386470930SIngo Molnar 43486470930SIngo Molnar fprintf(stderr, "\n"); 43586470930SIngo Molnar fprintf(stderr, "List of pre-defined events (to be used in -e):\n"); 43686470930SIngo Molnar 43786470930SIngo Molnar for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 43886470930SIngo Molnar type = syms->type + 1; 43986470930SIngo Molnar if (type > ARRAY_SIZE(event_type_descriptors)) 44086470930SIngo Molnar type = 0; 44186470930SIngo Molnar 44286470930SIngo Molnar if (type != prev_type) 44386470930SIngo Molnar fprintf(stderr, "\n"); 44486470930SIngo Molnar 44574d5b588SJaswinder Singh Rajput if (strlen(syms->alias)) 44674d5b588SJaswinder Singh Rajput sprintf(name, "%s OR %s", syms->symbol, syms->alias); 44774d5b588SJaswinder Singh Rajput else 44874d5b588SJaswinder Singh Rajput strcpy(name, syms->symbol); 44974d5b588SJaswinder Singh Rajput fprintf(stderr, " %-40s [%s]\n", name, 45086470930SIngo Molnar event_type_descriptors[type]); 45186470930SIngo Molnar 45286470930SIngo Molnar prev_type = type; 45386470930SIngo Molnar } 45486470930SIngo Molnar 45586470930SIngo Molnar fprintf(stderr, "\n"); 45674d5b588SJaswinder Singh Rajput fprintf(stderr, " %-40s [raw hardware event descriptor]\n", 45786470930SIngo Molnar "rNNN"); 45886470930SIngo Molnar fprintf(stderr, "\n"); 45986470930SIngo Molnar 46086470930SIngo Molnar exit(129); 46186470930SIngo Molnar } 462