186470930SIngo Molnar 286470930SIngo Molnar #include "util.h" 36b58e7f1SUlrich Drepper #include "../perf.h" 486470930SIngo Molnar #include "parse-options.h" 586470930SIngo Molnar #include "parse-events.h" 686470930SIngo Molnar #include "exec_cmd.h" 786470930SIngo Molnar #include "string.h" 85beeded1SJason Baron #include "cache.h" 98755a8f2SArjan van de Ven #include "header.h" 1086470930SIngo Molnar 1186470930SIngo Molnar int nr_counters; 1286470930SIngo Molnar 13cdd6c482SIngo Molnar struct perf_event_attr attrs[MAX_COUNTERS]; 1486470930SIngo Molnar 1586470930SIngo Molnar struct event_symbol { 169cffa8d5SPaul Mackerras u8 type; 179cffa8d5SPaul Mackerras u64 config; 1883a0944fSIngo Molnar const char *symbol; 1983a0944fSIngo Molnar const char *alias; 2086470930SIngo Molnar }; 2186470930SIngo Molnar 22bcd3279fSFrederic Weisbecker enum event_result { 23bcd3279fSFrederic Weisbecker EVT_FAILED, 24bcd3279fSFrederic Weisbecker EVT_HANDLED, 25bcd3279fSFrederic Weisbecker EVT_HANDLED_ALL 26bcd3279fSFrederic Weisbecker }; 27bcd3279fSFrederic Weisbecker 285beeded1SJason Baron char debugfs_path[MAXPATHLEN]; 295beeded1SJason Baron 3051e26842SJaswinder Singh Rajput #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 3151e26842SJaswinder Singh Rajput #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x 3286470930SIngo Molnar 3386470930SIngo Molnar static struct event_symbol event_symbols[] = { 3474d5b588SJaswinder Singh Rajput { CHW(CPU_CYCLES), "cpu-cycles", "cycles" }, 3574d5b588SJaswinder Singh Rajput { CHW(INSTRUCTIONS), "instructions", "" }, 3674d5b588SJaswinder Singh Rajput { CHW(CACHE_REFERENCES), "cache-references", "" }, 3774d5b588SJaswinder Singh Rajput { CHW(CACHE_MISSES), "cache-misses", "" }, 3874d5b588SJaswinder Singh Rajput { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" }, 3974d5b588SJaswinder Singh Rajput { CHW(BRANCH_MISSES), "branch-misses", "" }, 4074d5b588SJaswinder Singh Rajput { CHW(BUS_CYCLES), "bus-cycles", "" }, 4186470930SIngo Molnar 4274d5b588SJaswinder Singh Rajput { CSW(CPU_CLOCK), "cpu-clock", "" }, 4374d5b588SJaswinder Singh Rajput { CSW(TASK_CLOCK), "task-clock", "" }, 44c0c22dbfSJaswinder Singh Rajput { CSW(PAGE_FAULTS), "page-faults", "faults" }, 4574d5b588SJaswinder Singh Rajput { CSW(PAGE_FAULTS_MIN), "minor-faults", "" }, 4674d5b588SJaswinder Singh Rajput { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, 4774d5b588SJaswinder Singh Rajput { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, 4874d5b588SJaswinder Singh Rajput { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, 4986470930SIngo Molnar }; 5086470930SIngo Molnar 51cdd6c482SIngo Molnar #define __PERF_EVENT_FIELD(config, name) \ 52cdd6c482SIngo Molnar ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT) 5386470930SIngo Molnar 54cdd6c482SIngo Molnar #define PERF_EVENT_RAW(config) __PERF_EVENT_FIELD(config, RAW) 55cdd6c482SIngo Molnar #define PERF_EVENT_CONFIG(config) __PERF_EVENT_FIELD(config, CONFIG) 56cdd6c482SIngo Molnar #define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE) 57cdd6c482SIngo Molnar #define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT) 5886470930SIngo Molnar 5983a0944fSIngo Molnar static const char *hw_event_names[] = { 6086470930SIngo Molnar "cycles", 6186470930SIngo Molnar "instructions", 6286470930SIngo Molnar "cache-references", 6386470930SIngo Molnar "cache-misses", 6486470930SIngo Molnar "branches", 6586470930SIngo Molnar "branch-misses", 6686470930SIngo Molnar "bus-cycles", 6786470930SIngo Molnar }; 6886470930SIngo Molnar 6983a0944fSIngo Molnar static const char *sw_event_names[] = { 7044175b6fSIngo Molnar "cpu-clock-msecs", 7144175b6fSIngo Molnar "task-clock-msecs", 7286470930SIngo Molnar "page-faults", 7386470930SIngo Molnar "context-switches", 7486470930SIngo Molnar "CPU-migrations", 7586470930SIngo Molnar "minor-faults", 7686470930SIngo Molnar "major-faults", 7786470930SIngo Molnar }; 7886470930SIngo Molnar 7986470930SIngo Molnar #define MAX_ALIASES 8 8086470930SIngo Molnar 8183a0944fSIngo Molnar static const char *hw_cache[][MAX_ALIASES] = { 829590b7baSAnton Blanchard { "L1-dcache", "l1-d", "l1d", "L1-data", }, 839590b7baSAnton Blanchard { "L1-icache", "l1-i", "l1i", "L1-instruction", }, 84e5c59547SJaswinder Singh Rajput { "LLC", "L2" }, 85e5c59547SJaswinder Singh Rajput { "dTLB", "d-tlb", "Data-TLB", }, 86e5c59547SJaswinder Singh Rajput { "iTLB", "i-tlb", "Instruction-TLB", }, 87e5c59547SJaswinder Singh Rajput { "branch", "branches", "bpu", "btb", "bpc", }, 8886470930SIngo Molnar }; 8986470930SIngo Molnar 9083a0944fSIngo Molnar static const char *hw_cache_op[][MAX_ALIASES] = { 91e5c59547SJaswinder Singh Rajput { "load", "loads", "read", }, 92e5c59547SJaswinder Singh Rajput { "store", "stores", "write", }, 93e5c59547SJaswinder Singh Rajput { "prefetch", "prefetches", "speculative-read", "speculative-load", }, 9486470930SIngo Molnar }; 9586470930SIngo Molnar 9683a0944fSIngo Molnar static const char *hw_cache_result[][MAX_ALIASES] = { 97e5c59547SJaswinder Singh Rajput { "refs", "Reference", "ops", "access", }, 98e5c59547SJaswinder Singh Rajput { "misses", "miss", }, 9986470930SIngo Molnar }; 10086470930SIngo Molnar 10106813f6cSJaswinder Singh Rajput #define C(x) PERF_COUNT_HW_CACHE_##x 10206813f6cSJaswinder Singh Rajput #define CACHE_READ (1 << C(OP_READ)) 10306813f6cSJaswinder Singh Rajput #define CACHE_WRITE (1 << C(OP_WRITE)) 10406813f6cSJaswinder Singh Rajput #define CACHE_PREFETCH (1 << C(OP_PREFETCH)) 10506813f6cSJaswinder Singh Rajput #define COP(x) (1 << x) 10606813f6cSJaswinder Singh Rajput 10706813f6cSJaswinder Singh Rajput /* 10806813f6cSJaswinder Singh Rajput * cache operartion stat 10906813f6cSJaswinder Singh Rajput * L1I : Read and prefetch only 11006813f6cSJaswinder Singh Rajput * ITLB and BPU : Read-only 11106813f6cSJaswinder Singh Rajput */ 11206813f6cSJaswinder Singh Rajput static unsigned long hw_cache_stat[C(MAX)] = { 11306813f6cSJaswinder Singh Rajput [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 11406813f6cSJaswinder Singh Rajput [C(L1I)] = (CACHE_READ | CACHE_PREFETCH), 11506813f6cSJaswinder Singh Rajput [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 11606813f6cSJaswinder Singh Rajput [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 11706813f6cSJaswinder Singh Rajput [C(ITLB)] = (CACHE_READ), 11806813f6cSJaswinder Singh Rajput [C(BPU)] = (CACHE_READ), 11906813f6cSJaswinder Singh Rajput }; 12006813f6cSJaswinder Singh Rajput 1216b58e7f1SUlrich Drepper #define for_each_subsystem(sys_dir, sys_dirent, sys_next) \ 122f6bdafefSJason Baron while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ 1236b58e7f1SUlrich Drepper if (sys_dirent.d_type == DT_DIR && \ 124f6bdafefSJason Baron (strcmp(sys_dirent.d_name, ".")) && \ 125f6bdafefSJason Baron (strcmp(sys_dirent.d_name, ".."))) 126f6bdafefSJason Baron 127ae07b63fSPeter Zijlstra static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir) 128ae07b63fSPeter Zijlstra { 129ae07b63fSPeter Zijlstra char evt_path[MAXPATHLEN]; 130ae07b63fSPeter Zijlstra int fd; 131ae07b63fSPeter Zijlstra 132ae07b63fSPeter Zijlstra snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 133ae07b63fSPeter Zijlstra sys_dir->d_name, evt_dir->d_name); 134ae07b63fSPeter Zijlstra fd = open(evt_path, O_RDONLY); 135ae07b63fSPeter Zijlstra if (fd < 0) 136ae07b63fSPeter Zijlstra return -EINVAL; 137ae07b63fSPeter Zijlstra close(fd); 138ae07b63fSPeter Zijlstra 139ae07b63fSPeter Zijlstra return 0; 140ae07b63fSPeter Zijlstra } 141ae07b63fSPeter Zijlstra 1426b58e7f1SUlrich Drepper #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) \ 143f6bdafefSJason Baron while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \ 1446b58e7f1SUlrich Drepper if (evt_dirent.d_type == DT_DIR && \ 145f6bdafefSJason Baron (strcmp(evt_dirent.d_name, ".")) && \ 146ae07b63fSPeter Zijlstra (strcmp(evt_dirent.d_name, "..")) && \ 147ae07b63fSPeter Zijlstra (!tp_event_has_id(&sys_dirent, &evt_dirent))) 148f6bdafefSJason Baron 149270bbbe8SLi Zefan #define MAX_EVENT_LENGTH 512 150f6bdafefSJason Baron 1515beeded1SJason Baron int valid_debugfs_mount(const char *debugfs) 152f6bdafefSJason Baron { 153f6bdafefSJason Baron struct statfs st_fs; 154f6bdafefSJason Baron 1555beeded1SJason Baron if (statfs(debugfs, &st_fs) < 0) 156f6bdafefSJason Baron return -ENOENT; 157f6bdafefSJason Baron else if (st_fs.f_type != (long) DEBUGFS_MAGIC) 158f6bdafefSJason Baron return -ENOENT; 159f6bdafefSJason Baron return 0; 160f6bdafefSJason Baron } 161f6bdafefSJason Baron 1621ef2ed10SFrederic Weisbecker struct tracepoint_path *tracepoint_id_to_path(u64 config) 163f6bdafefSJason Baron { 1641ef2ed10SFrederic Weisbecker struct tracepoint_path *path = NULL; 165f6bdafefSJason Baron DIR *sys_dir, *evt_dir; 166f6bdafefSJason Baron struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 167f6bdafefSJason Baron char id_buf[4]; 168725b1368SEric Dumazet int fd; 169f6bdafefSJason Baron u64 id; 170f6bdafefSJason Baron char evt_path[MAXPATHLEN]; 171725b1368SEric Dumazet char dir_path[MAXPATHLEN]; 172f6bdafefSJason Baron 1735beeded1SJason Baron if (valid_debugfs_mount(debugfs_path)) 1741ef2ed10SFrederic Weisbecker return NULL; 175f6bdafefSJason Baron 1765beeded1SJason Baron sys_dir = opendir(debugfs_path); 177f6bdafefSJason Baron if (!sys_dir) 178725b1368SEric Dumazet return NULL; 179f6bdafefSJason Baron 1806b58e7f1SUlrich Drepper for_each_subsystem(sys_dir, sys_dirent, sys_next) { 181725b1368SEric Dumazet 182725b1368SEric Dumazet snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 183725b1368SEric Dumazet sys_dirent.d_name); 184725b1368SEric Dumazet evt_dir = opendir(dir_path); 185725b1368SEric Dumazet if (!evt_dir) 1866b58e7f1SUlrich Drepper continue; 187725b1368SEric Dumazet 1886b58e7f1SUlrich Drepper for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 189725b1368SEric Dumazet 190725b1368SEric Dumazet snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, 191f6bdafefSJason Baron evt_dirent.d_name); 192725b1368SEric Dumazet fd = open(evt_path, O_RDONLY); 193f6bdafefSJason Baron if (fd < 0) 194f6bdafefSJason Baron continue; 195f6bdafefSJason Baron if (read(fd, id_buf, sizeof(id_buf)) < 0) { 196f6bdafefSJason Baron close(fd); 197f6bdafefSJason Baron continue; 198f6bdafefSJason Baron } 199f6bdafefSJason Baron close(fd); 200f6bdafefSJason Baron id = atoll(id_buf); 201f6bdafefSJason Baron if (id == config) { 202f6bdafefSJason Baron closedir(evt_dir); 203f6bdafefSJason Baron closedir(sys_dir); 2041ef2ed10SFrederic Weisbecker path = calloc(1, sizeof(path)); 2051ef2ed10SFrederic Weisbecker path->system = malloc(MAX_EVENT_LENGTH); 2061ef2ed10SFrederic Weisbecker if (!path->system) { 2071ef2ed10SFrederic Weisbecker free(path); 2081ef2ed10SFrederic Weisbecker return NULL; 2091ef2ed10SFrederic Weisbecker } 2101ef2ed10SFrederic Weisbecker path->name = malloc(MAX_EVENT_LENGTH); 2111ef2ed10SFrederic Weisbecker if (!path->name) { 2121ef2ed10SFrederic Weisbecker free(path->system); 2131ef2ed10SFrederic Weisbecker free(path); 2141ef2ed10SFrederic Weisbecker return NULL; 2151ef2ed10SFrederic Weisbecker } 2161ef2ed10SFrederic Weisbecker strncpy(path->system, sys_dirent.d_name, 2171ef2ed10SFrederic Weisbecker MAX_EVENT_LENGTH); 2181ef2ed10SFrederic Weisbecker strncpy(path->name, evt_dirent.d_name, 2191ef2ed10SFrederic Weisbecker MAX_EVENT_LENGTH); 2201ef2ed10SFrederic Weisbecker return path; 221f6bdafefSJason Baron } 222f6bdafefSJason Baron } 223f6bdafefSJason Baron closedir(evt_dir); 224f6bdafefSJason Baron } 225f6bdafefSJason Baron 226f6bdafefSJason Baron closedir(sys_dir); 2271ef2ed10SFrederic Weisbecker return NULL; 2281ef2ed10SFrederic Weisbecker } 2291ef2ed10SFrederic Weisbecker 2301ef2ed10SFrederic Weisbecker #define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1) 2311ef2ed10SFrederic Weisbecker static const char *tracepoint_id_to_name(u64 config) 2321ef2ed10SFrederic Weisbecker { 2331ef2ed10SFrederic Weisbecker static char buf[TP_PATH_LEN]; 2341ef2ed10SFrederic Weisbecker struct tracepoint_path *path; 2351ef2ed10SFrederic Weisbecker 2361ef2ed10SFrederic Weisbecker path = tracepoint_id_to_path(config); 2371ef2ed10SFrederic Weisbecker if (path) { 2381ef2ed10SFrederic Weisbecker snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name); 2391ef2ed10SFrederic Weisbecker free(path->name); 2401ef2ed10SFrederic Weisbecker free(path->system); 2411ef2ed10SFrederic Weisbecker free(path); 2421ef2ed10SFrederic Weisbecker } else 2431ef2ed10SFrederic Weisbecker snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown"); 2441ef2ed10SFrederic Weisbecker 2451ef2ed10SFrederic Weisbecker return buf; 246f6bdafefSJason Baron } 247f6bdafefSJason Baron 24806813f6cSJaswinder Singh Rajput static int is_cache_op_valid(u8 cache_type, u8 cache_op) 24906813f6cSJaswinder Singh Rajput { 25006813f6cSJaswinder Singh Rajput if (hw_cache_stat[cache_type] & COP(cache_op)) 25106813f6cSJaswinder Singh Rajput return 1; /* valid */ 25206813f6cSJaswinder Singh Rajput else 25306813f6cSJaswinder Singh Rajput return 0; /* invalid */ 25406813f6cSJaswinder Singh Rajput } 25506813f6cSJaswinder Singh Rajput 256e5c59547SJaswinder Singh Rajput static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result) 257e5c59547SJaswinder Singh Rajput { 258e5c59547SJaswinder Singh Rajput static char name[50]; 259e5c59547SJaswinder Singh Rajput 260e5c59547SJaswinder Singh Rajput if (cache_result) { 261e5c59547SJaswinder Singh Rajput sprintf(name, "%s-%s-%s", hw_cache[cache_type][0], 262e5c59547SJaswinder Singh Rajput hw_cache_op[cache_op][0], 263e5c59547SJaswinder Singh Rajput hw_cache_result[cache_result][0]); 264e5c59547SJaswinder Singh Rajput } else { 265e5c59547SJaswinder Singh Rajput sprintf(name, "%s-%s", hw_cache[cache_type][0], 266e5c59547SJaswinder Singh Rajput hw_cache_op[cache_op][1]); 267e5c59547SJaswinder Singh Rajput } 268e5c59547SJaswinder Singh Rajput 269e5c59547SJaswinder Singh Rajput return name; 270e5c59547SJaswinder Singh Rajput } 271e5c59547SJaswinder Singh Rajput 27283a0944fSIngo Molnar const char *event_name(int counter) 27386470930SIngo Molnar { 2749cffa8d5SPaul Mackerras u64 config = attrs[counter].config; 27586470930SIngo Molnar int type = attrs[counter].type; 2768f18aec5SPeter Zijlstra 2778f18aec5SPeter Zijlstra return __event_name(type, config); 2788f18aec5SPeter Zijlstra } 2798f18aec5SPeter Zijlstra 28083a0944fSIngo Molnar const char *__event_name(int type, u64 config) 2818f18aec5SPeter Zijlstra { 28286470930SIngo Molnar static char buf[32]; 28386470930SIngo Molnar 2848f18aec5SPeter Zijlstra if (type == PERF_TYPE_RAW) { 28586470930SIngo Molnar sprintf(buf, "raw 0x%llx", config); 28686470930SIngo Molnar return buf; 28786470930SIngo Molnar } 28886470930SIngo Molnar 28986470930SIngo Molnar switch (type) { 29086470930SIngo Molnar case PERF_TYPE_HARDWARE: 291f4dbfa8fSPeter Zijlstra if (config < PERF_COUNT_HW_MAX) 29286470930SIngo Molnar return hw_event_names[config]; 29386470930SIngo Molnar return "unknown-hardware"; 29486470930SIngo Molnar 29586470930SIngo Molnar case PERF_TYPE_HW_CACHE: { 2969cffa8d5SPaul Mackerras u8 cache_type, cache_op, cache_result; 29786470930SIngo Molnar 29886470930SIngo Molnar cache_type = (config >> 0) & 0xff; 29986470930SIngo Molnar if (cache_type > PERF_COUNT_HW_CACHE_MAX) 30086470930SIngo Molnar return "unknown-ext-hardware-cache-type"; 30186470930SIngo Molnar 30286470930SIngo Molnar cache_op = (config >> 8) & 0xff; 30386470930SIngo Molnar if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX) 30486470930SIngo Molnar return "unknown-ext-hardware-cache-op"; 30586470930SIngo Molnar 30686470930SIngo Molnar cache_result = (config >> 16) & 0xff; 30786470930SIngo Molnar if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX) 30886470930SIngo Molnar return "unknown-ext-hardware-cache-result"; 30986470930SIngo Molnar 31006813f6cSJaswinder Singh Rajput if (!is_cache_op_valid(cache_type, cache_op)) 31106813f6cSJaswinder Singh Rajput return "invalid-cache"; 31286470930SIngo Molnar 313e5c59547SJaswinder Singh Rajput return event_cache_name(cache_type, cache_op, cache_result); 31486470930SIngo Molnar } 31586470930SIngo Molnar 31686470930SIngo Molnar case PERF_TYPE_SOFTWARE: 317f4dbfa8fSPeter Zijlstra if (config < PERF_COUNT_SW_MAX) 31886470930SIngo Molnar return sw_event_names[config]; 31986470930SIngo Molnar return "unknown-software"; 32086470930SIngo Molnar 321f6bdafefSJason Baron case PERF_TYPE_TRACEPOINT: 322f6bdafefSJason Baron return tracepoint_id_to_name(config); 323f6bdafefSJason Baron 32486470930SIngo Molnar default: 32586470930SIngo Molnar break; 32686470930SIngo Molnar } 32786470930SIngo Molnar 32886470930SIngo Molnar return "unknown"; 32986470930SIngo Molnar } 33086470930SIngo Molnar 33183a0944fSIngo Molnar static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size) 33286470930SIngo Molnar { 33386470930SIngo Molnar int i, j; 33461c45981SPaul Mackerras int n, longest = -1; 33586470930SIngo Molnar 33686470930SIngo Molnar for (i = 0; i < size; i++) { 33761c45981SPaul Mackerras for (j = 0; j < MAX_ALIASES && names[i][j]; j++) { 33861c45981SPaul Mackerras n = strlen(names[i][j]); 33961c45981SPaul Mackerras if (n > longest && !strncasecmp(*str, names[i][j], n)) 34061c45981SPaul Mackerras longest = n; 34161c45981SPaul Mackerras } 34261c45981SPaul Mackerras if (longest > 0) { 34361c45981SPaul Mackerras *str += longest; 34486470930SIngo Molnar return i; 34586470930SIngo Molnar } 34686470930SIngo Molnar } 34786470930SIngo Molnar 3488953645fSIngo Molnar return -1; 34986470930SIngo Molnar } 35086470930SIngo Molnar 351bcd3279fSFrederic Weisbecker static enum event_result 352cdd6c482SIngo Molnar parse_generic_hw_event(const char **str, struct perf_event_attr *attr) 35386470930SIngo Molnar { 35461c45981SPaul Mackerras const char *s = *str; 35561c45981SPaul Mackerras int cache_type = -1, cache_op = -1, cache_result = -1; 35686470930SIngo Molnar 35761c45981SPaul Mackerras cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX); 35886470930SIngo Molnar /* 35986470930SIngo Molnar * No fallback - if we cannot get a clear cache type 36086470930SIngo Molnar * then bail out: 36186470930SIngo Molnar */ 36286470930SIngo Molnar if (cache_type == -1) 363bcd3279fSFrederic Weisbecker return EVT_FAILED; 36486470930SIngo Molnar 36561c45981SPaul Mackerras while ((cache_op == -1 || cache_result == -1) && *s == '-') { 36661c45981SPaul Mackerras ++s; 36761c45981SPaul Mackerras 36861c45981SPaul Mackerras if (cache_op == -1) { 36961c45981SPaul Mackerras cache_op = parse_aliases(&s, hw_cache_op, 37061c45981SPaul Mackerras PERF_COUNT_HW_CACHE_OP_MAX); 37161c45981SPaul Mackerras if (cache_op >= 0) { 37261c45981SPaul Mackerras if (!is_cache_op_valid(cache_type, cache_op)) 37361c45981SPaul Mackerras return 0; 37461c45981SPaul Mackerras continue; 37561c45981SPaul Mackerras } 37661c45981SPaul Mackerras } 37761c45981SPaul Mackerras 37861c45981SPaul Mackerras if (cache_result == -1) { 37961c45981SPaul Mackerras cache_result = parse_aliases(&s, hw_cache_result, 38061c45981SPaul Mackerras PERF_COUNT_HW_CACHE_RESULT_MAX); 38161c45981SPaul Mackerras if (cache_result >= 0) 38261c45981SPaul Mackerras continue; 38361c45981SPaul Mackerras } 38461c45981SPaul Mackerras 38561c45981SPaul Mackerras /* 38661c45981SPaul Mackerras * Can't parse this as a cache op or result, so back up 38761c45981SPaul Mackerras * to the '-'. 38861c45981SPaul Mackerras */ 38961c45981SPaul Mackerras --s; 39061c45981SPaul Mackerras break; 39161c45981SPaul Mackerras } 39261c45981SPaul Mackerras 39386470930SIngo Molnar /* 39486470930SIngo Molnar * Fall back to reads: 39586470930SIngo Molnar */ 3968953645fSIngo Molnar if (cache_op == -1) 3978953645fSIngo Molnar cache_op = PERF_COUNT_HW_CACHE_OP_READ; 39886470930SIngo Molnar 39986470930SIngo Molnar /* 40086470930SIngo Molnar * Fall back to accesses: 40186470930SIngo Molnar */ 40286470930SIngo Molnar if (cache_result == -1) 40386470930SIngo Molnar cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS; 40486470930SIngo Molnar 40586470930SIngo Molnar attr->config = cache_type | (cache_op << 8) | (cache_result << 16); 40686470930SIngo Molnar attr->type = PERF_TYPE_HW_CACHE; 40786470930SIngo Molnar 40861c45981SPaul Mackerras *str = s; 409bcd3279fSFrederic Weisbecker return EVT_HANDLED; 41086470930SIngo Molnar } 41186470930SIngo Molnar 412bcd3279fSFrederic Weisbecker static enum event_result 413bcd3279fSFrederic Weisbecker parse_single_tracepoint_event(char *sys_name, 414bcd3279fSFrederic Weisbecker const char *evt_name, 415bcd3279fSFrederic Weisbecker unsigned int evt_length, 416bcd3279fSFrederic Weisbecker char *flags, 417cdd6c482SIngo Molnar struct perf_event_attr *attr, 418bcd3279fSFrederic Weisbecker const char **strp) 419bcd3279fSFrederic Weisbecker { 420bcd3279fSFrederic Weisbecker char evt_path[MAXPATHLEN]; 421bcd3279fSFrederic Weisbecker char id_buf[4]; 422bcd3279fSFrederic Weisbecker u64 id; 423bcd3279fSFrederic Weisbecker int fd; 424bcd3279fSFrederic Weisbecker 425bcd3279fSFrederic Weisbecker if (flags) { 4261281a49bSLi Zefan if (!strncmp(flags, "record", strlen(flags))) { 427bcd3279fSFrederic Weisbecker attr->sample_type |= PERF_SAMPLE_RAW; 4281281a49bSLi Zefan attr->sample_type |= PERF_SAMPLE_TIME; 4291281a49bSLi Zefan attr->sample_type |= PERF_SAMPLE_CPU; 4301281a49bSLi Zefan } 431bcd3279fSFrederic Weisbecker } 432bcd3279fSFrederic Weisbecker 433bcd3279fSFrederic Weisbecker snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 434bcd3279fSFrederic Weisbecker sys_name, evt_name); 435bcd3279fSFrederic Weisbecker 436bcd3279fSFrederic Weisbecker fd = open(evt_path, O_RDONLY); 437bcd3279fSFrederic Weisbecker if (fd < 0) 438bcd3279fSFrederic Weisbecker return EVT_FAILED; 439bcd3279fSFrederic Weisbecker 440bcd3279fSFrederic Weisbecker if (read(fd, id_buf, sizeof(id_buf)) < 0) { 441bcd3279fSFrederic Weisbecker close(fd); 442bcd3279fSFrederic Weisbecker return EVT_FAILED; 443bcd3279fSFrederic Weisbecker } 444bcd3279fSFrederic Weisbecker 445bcd3279fSFrederic Weisbecker close(fd); 446bcd3279fSFrederic Weisbecker id = atoll(id_buf); 447bcd3279fSFrederic Weisbecker attr->config = id; 448bcd3279fSFrederic Weisbecker attr->type = PERF_TYPE_TRACEPOINT; 449bcd3279fSFrederic Weisbecker *strp = evt_name + evt_length; 450bcd3279fSFrederic Weisbecker 451bcd3279fSFrederic Weisbecker return EVT_HANDLED; 452bcd3279fSFrederic Weisbecker } 453bcd3279fSFrederic Weisbecker 454bcd3279fSFrederic Weisbecker /* sys + ':' + event + ':' + flags*/ 455bcd3279fSFrederic Weisbecker #define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128) 456bcd3279fSFrederic Weisbecker static enum event_result 457bcd3279fSFrederic Weisbecker parse_subsystem_tracepoint_event(char *sys_name, char *flags) 458bcd3279fSFrederic Weisbecker { 459bcd3279fSFrederic Weisbecker char evt_path[MAXPATHLEN]; 460bcd3279fSFrederic Weisbecker struct dirent *evt_ent; 461bcd3279fSFrederic Weisbecker DIR *evt_dir; 462bcd3279fSFrederic Weisbecker 463bcd3279fSFrederic Weisbecker snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name); 464bcd3279fSFrederic Weisbecker evt_dir = opendir(evt_path); 465bcd3279fSFrederic Weisbecker 466bcd3279fSFrederic Weisbecker if (!evt_dir) { 467bcd3279fSFrederic Weisbecker perror("Can't open event dir"); 468bcd3279fSFrederic Weisbecker return EVT_FAILED; 469bcd3279fSFrederic Weisbecker } 470bcd3279fSFrederic Weisbecker 471bcd3279fSFrederic Weisbecker while ((evt_ent = readdir(evt_dir))) { 472bcd3279fSFrederic Weisbecker char event_opt[MAX_EVOPT_LEN + 1]; 473bcd3279fSFrederic Weisbecker int len; 474bcd3279fSFrederic Weisbecker unsigned int rem = MAX_EVOPT_LEN; 475bcd3279fSFrederic Weisbecker 476bcd3279fSFrederic Weisbecker if (!strcmp(evt_ent->d_name, ".") 477bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "..") 478bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "enable") 479bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "filter")) 480bcd3279fSFrederic Weisbecker continue; 481bcd3279fSFrederic Weisbecker 482bcd3279fSFrederic Weisbecker len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s", sys_name, 483bcd3279fSFrederic Weisbecker evt_ent->d_name); 484bcd3279fSFrederic Weisbecker if (len < 0) 485bcd3279fSFrederic Weisbecker return EVT_FAILED; 486bcd3279fSFrederic Weisbecker 487bcd3279fSFrederic Weisbecker rem -= len; 488bcd3279fSFrederic Weisbecker if (flags) { 489bcd3279fSFrederic Weisbecker if (rem < strlen(flags) + 1) 490bcd3279fSFrederic Weisbecker return EVT_FAILED; 491bcd3279fSFrederic Weisbecker 492bcd3279fSFrederic Weisbecker strcat(event_opt, ":"); 493bcd3279fSFrederic Weisbecker strcat(event_opt, flags); 494bcd3279fSFrederic Weisbecker } 495bcd3279fSFrederic Weisbecker 496bcd3279fSFrederic Weisbecker if (parse_events(NULL, event_opt, 0)) 497bcd3279fSFrederic Weisbecker return EVT_FAILED; 498bcd3279fSFrederic Weisbecker } 499bcd3279fSFrederic Weisbecker 500bcd3279fSFrederic Weisbecker return EVT_HANDLED_ALL; 501bcd3279fSFrederic Weisbecker } 502bcd3279fSFrederic Weisbecker 503bcd3279fSFrederic Weisbecker 504bcd3279fSFrederic Weisbecker static enum event_result parse_tracepoint_event(const char **strp, 505cdd6c482SIngo Molnar struct perf_event_attr *attr) 506f6bdafefSJason Baron { 507f6bdafefSJason Baron const char *evt_name; 5083a9f131fSFrederic Weisbecker char *flags; 509f6bdafefSJason Baron char sys_name[MAX_EVENT_LENGTH]; 510f6bdafefSJason Baron unsigned int sys_length, evt_length; 511f6bdafefSJason Baron 5125beeded1SJason Baron if (valid_debugfs_mount(debugfs_path)) 513f6bdafefSJason Baron return 0; 514f6bdafefSJason Baron 515f6bdafefSJason Baron evt_name = strchr(*strp, ':'); 516f6bdafefSJason Baron if (!evt_name) 517bcd3279fSFrederic Weisbecker return EVT_FAILED; 518f6bdafefSJason Baron 519f6bdafefSJason Baron sys_length = evt_name - *strp; 520f6bdafefSJason Baron if (sys_length >= MAX_EVENT_LENGTH) 521f6bdafefSJason Baron return 0; 522f6bdafefSJason Baron 523f6bdafefSJason Baron strncpy(sys_name, *strp, sys_length); 524f6bdafefSJason Baron sys_name[sys_length] = '\0'; 525f6bdafefSJason Baron evt_name = evt_name + 1; 5263a9f131fSFrederic Weisbecker 5273a9f131fSFrederic Weisbecker flags = strchr(evt_name, ':'); 5283a9f131fSFrederic Weisbecker if (flags) { 5291fc35b29SIngo Molnar /* split it out: */ 5301fc35b29SIngo Molnar evt_name = strndup(evt_name, flags - evt_name); 5313a9f131fSFrederic Weisbecker flags++; 5323a9f131fSFrederic Weisbecker } 5333a9f131fSFrederic Weisbecker 534f6bdafefSJason Baron evt_length = strlen(evt_name); 535f6bdafefSJason Baron if (evt_length >= MAX_EVENT_LENGTH) 536bcd3279fSFrederic Weisbecker return EVT_FAILED; 537f6bdafefSJason Baron 538bcd3279fSFrederic Weisbecker if (!strcmp(evt_name, "*")) { 539f6bdafefSJason Baron *strp = evt_name + evt_length; 540bcd3279fSFrederic Weisbecker return parse_subsystem_tracepoint_event(sys_name, flags); 541bcd3279fSFrederic Weisbecker } else 542bcd3279fSFrederic Weisbecker return parse_single_tracepoint_event(sys_name, evt_name, 543bcd3279fSFrederic Weisbecker evt_length, flags, 544bcd3279fSFrederic Weisbecker attr, strp); 545f6bdafefSJason Baron } 546f6bdafefSJason Baron 54774d5b588SJaswinder Singh Rajput static int check_events(const char *str, unsigned int i) 54874d5b588SJaswinder Singh Rajput { 54961c45981SPaul Mackerras int n; 55074d5b588SJaswinder Singh Rajput 55161c45981SPaul Mackerras n = strlen(event_symbols[i].symbol); 55261c45981SPaul Mackerras if (!strncmp(str, event_symbols[i].symbol, n)) 55361c45981SPaul Mackerras return n; 55461c45981SPaul Mackerras 55561c45981SPaul Mackerras n = strlen(event_symbols[i].alias); 55661c45981SPaul Mackerras if (n) 55761c45981SPaul Mackerras if (!strncmp(str, event_symbols[i].alias, n)) 55861c45981SPaul Mackerras return n; 55961c45981SPaul Mackerras return 0; 56061c45981SPaul Mackerras } 56161c45981SPaul Mackerras 562bcd3279fSFrederic Weisbecker static enum event_result 563cdd6c482SIngo Molnar parse_symbolic_event(const char **strp, struct perf_event_attr *attr) 56461c45981SPaul Mackerras { 56561c45981SPaul Mackerras const char *str = *strp; 56661c45981SPaul Mackerras unsigned int i; 56761c45981SPaul Mackerras int n; 56861c45981SPaul Mackerras 56961c45981SPaul Mackerras for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { 57061c45981SPaul Mackerras n = check_events(str, i); 57161c45981SPaul Mackerras if (n > 0) { 57261c45981SPaul Mackerras attr->type = event_symbols[i].type; 57361c45981SPaul Mackerras attr->config = event_symbols[i].config; 57461c45981SPaul Mackerras *strp = str + n; 575bcd3279fSFrederic Weisbecker return EVT_HANDLED; 57661c45981SPaul Mackerras } 57761c45981SPaul Mackerras } 578bcd3279fSFrederic Weisbecker return EVT_FAILED; 57961c45981SPaul Mackerras } 58061c45981SPaul Mackerras 581bcd3279fSFrederic Weisbecker static enum event_result 582cdd6c482SIngo Molnar parse_raw_event(const char **strp, struct perf_event_attr *attr) 58361c45981SPaul Mackerras { 58461c45981SPaul Mackerras const char *str = *strp; 58561c45981SPaul Mackerras u64 config; 58661c45981SPaul Mackerras int n; 58761c45981SPaul Mackerras 58861c45981SPaul Mackerras if (*str != 'r') 589bcd3279fSFrederic Weisbecker return EVT_FAILED; 59061c45981SPaul Mackerras n = hex2u64(str + 1, &config); 59161c45981SPaul Mackerras if (n > 0) { 59261c45981SPaul Mackerras *strp = str + n + 1; 59361c45981SPaul Mackerras attr->type = PERF_TYPE_RAW; 59461c45981SPaul Mackerras attr->config = config; 595bcd3279fSFrederic Weisbecker return EVT_HANDLED; 59661c45981SPaul Mackerras } 597bcd3279fSFrederic Weisbecker return EVT_FAILED; 59861c45981SPaul Mackerras } 59961c45981SPaul Mackerras 600bcd3279fSFrederic Weisbecker static enum event_result 601cdd6c482SIngo Molnar parse_numeric_event(const char **strp, struct perf_event_attr *attr) 60261c45981SPaul Mackerras { 60361c45981SPaul Mackerras const char *str = *strp; 60461c45981SPaul Mackerras char *endp; 60561c45981SPaul Mackerras unsigned long type; 60661c45981SPaul Mackerras u64 config; 60761c45981SPaul Mackerras 60861c45981SPaul Mackerras type = strtoul(str, &endp, 0); 60961c45981SPaul Mackerras if (endp > str && type < PERF_TYPE_MAX && *endp == ':') { 61061c45981SPaul Mackerras str = endp + 1; 61161c45981SPaul Mackerras config = strtoul(str, &endp, 0); 61261c45981SPaul Mackerras if (endp > str) { 61361c45981SPaul Mackerras attr->type = type; 61461c45981SPaul Mackerras attr->config = config; 61561c45981SPaul Mackerras *strp = endp; 616bcd3279fSFrederic Weisbecker return EVT_HANDLED; 61761c45981SPaul Mackerras } 61861c45981SPaul Mackerras } 619bcd3279fSFrederic Weisbecker return EVT_FAILED; 62061c45981SPaul Mackerras } 62161c45981SPaul Mackerras 622bcd3279fSFrederic Weisbecker static enum event_result 623cdd6c482SIngo Molnar parse_event_modifier(const char **strp, struct perf_event_attr *attr) 62461c45981SPaul Mackerras { 62561c45981SPaul Mackerras const char *str = *strp; 62661c45981SPaul Mackerras int eu = 1, ek = 1, eh = 1; 62761c45981SPaul Mackerras 62861c45981SPaul Mackerras if (*str++ != ':') 62961c45981SPaul Mackerras return 0; 63061c45981SPaul Mackerras while (*str) { 63161c45981SPaul Mackerras if (*str == 'u') 63261c45981SPaul Mackerras eu = 0; 63361c45981SPaul Mackerras else if (*str == 'k') 63461c45981SPaul Mackerras ek = 0; 63561c45981SPaul Mackerras else if (*str == 'h') 63661c45981SPaul Mackerras eh = 0; 63761c45981SPaul Mackerras else 63861c45981SPaul Mackerras break; 63961c45981SPaul Mackerras ++str; 64061c45981SPaul Mackerras } 64161c45981SPaul Mackerras if (str >= *strp + 2) { 64261c45981SPaul Mackerras *strp = str; 64361c45981SPaul Mackerras attr->exclude_user = eu; 64461c45981SPaul Mackerras attr->exclude_kernel = ek; 64561c45981SPaul Mackerras attr->exclude_hv = eh; 64661c45981SPaul Mackerras return 1; 64761c45981SPaul Mackerras } 64874d5b588SJaswinder Singh Rajput return 0; 64974d5b588SJaswinder Singh Rajput } 65074d5b588SJaswinder Singh Rajput 65186470930SIngo Molnar /* 65286470930SIngo Molnar * Each event can have multiple symbolic names. 65386470930SIngo Molnar * Symbolic names are (almost) exactly matched. 65486470930SIngo Molnar */ 655bcd3279fSFrederic Weisbecker static enum event_result 656cdd6c482SIngo Molnar parse_event_symbols(const char **str, struct perf_event_attr *attr) 65786470930SIngo Molnar { 658bcd3279fSFrederic Weisbecker enum event_result ret; 65986470930SIngo Molnar 660bcd3279fSFrederic Weisbecker ret = parse_tracepoint_event(str, attr); 661bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 662bcd3279fSFrederic Weisbecker goto modifier; 663bcd3279fSFrederic Weisbecker 664bcd3279fSFrederic Weisbecker ret = parse_raw_event(str, attr); 665bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 666bcd3279fSFrederic Weisbecker goto modifier; 667bcd3279fSFrederic Weisbecker 668bcd3279fSFrederic Weisbecker ret = parse_numeric_event(str, attr); 669bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 670bcd3279fSFrederic Weisbecker goto modifier; 671bcd3279fSFrederic Weisbecker 672bcd3279fSFrederic Weisbecker ret = parse_symbolic_event(str, attr); 673bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 674bcd3279fSFrederic Weisbecker goto modifier; 675bcd3279fSFrederic Weisbecker 676bcd3279fSFrederic Weisbecker ret = parse_generic_hw_event(str, attr); 677bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 678bcd3279fSFrederic Weisbecker goto modifier; 679bcd3279fSFrederic Weisbecker 680bcd3279fSFrederic Weisbecker return EVT_FAILED; 681bcd3279fSFrederic Weisbecker 682bcd3279fSFrederic Weisbecker modifier: 68361c45981SPaul Mackerras parse_event_modifier(str, attr); 68486470930SIngo Molnar 685bcd3279fSFrederic Weisbecker return ret; 68686470930SIngo Molnar } 68786470930SIngo Molnar 6888755a8f2SArjan van de Ven static void store_event_type(const char *orgname) 6898755a8f2SArjan van de Ven { 6908755a8f2SArjan van de Ven char filename[PATH_MAX], *c; 6918755a8f2SArjan van de Ven FILE *file; 6928755a8f2SArjan van de Ven int id; 6938755a8f2SArjan van de Ven 694*63c9e01eSAshwin Chaugule sprintf(filename, "%s/", debugfs_path); 695*63c9e01eSAshwin Chaugule strncat(filename, orgname, strlen(orgname)); 696*63c9e01eSAshwin Chaugule strcat(filename, "/id"); 697*63c9e01eSAshwin Chaugule 6988755a8f2SArjan van de Ven c = strchr(filename, ':'); 6998755a8f2SArjan van de Ven if (c) 7008755a8f2SArjan van de Ven *c = '/'; 7018755a8f2SArjan van de Ven 7028755a8f2SArjan van de Ven file = fopen(filename, "r"); 7038755a8f2SArjan van de Ven if (!file) 7048755a8f2SArjan van de Ven return; 7058755a8f2SArjan van de Ven if (fscanf(file, "%i", &id) < 1) 7068755a8f2SArjan van de Ven die("cannot store event ID"); 7078755a8f2SArjan van de Ven fclose(file); 7088755a8f2SArjan van de Ven perf_header__push_event(id, orgname); 7098755a8f2SArjan van de Ven } 7108755a8f2SArjan van de Ven 7118755a8f2SArjan van de Ven 712f37a291cSIngo Molnar int parse_events(const struct option *opt __used, const char *str, int unset __used) 71386470930SIngo Molnar { 714cdd6c482SIngo Molnar struct perf_event_attr attr; 715bcd3279fSFrederic Weisbecker enum event_result ret; 71686470930SIngo Molnar 7178755a8f2SArjan van de Ven if (strchr(str, ':')) 7188755a8f2SArjan van de Ven store_event_type(str); 7198755a8f2SArjan van de Ven 72061c45981SPaul Mackerras for (;;) { 72186470930SIngo Molnar if (nr_counters == MAX_COUNTERS) 72286470930SIngo Molnar return -1; 72386470930SIngo Molnar 72461c45981SPaul Mackerras memset(&attr, 0, sizeof(attr)); 725bcd3279fSFrederic Weisbecker ret = parse_event_symbols(&str, &attr); 726bcd3279fSFrederic Weisbecker if (ret == EVT_FAILED) 72761c45981SPaul Mackerras return -1; 72861c45981SPaul Mackerras 72961c45981SPaul Mackerras if (!(*str == 0 || *str == ',' || isspace(*str))) 73061c45981SPaul Mackerras return -1; 73186470930SIngo Molnar 732bcd3279fSFrederic Weisbecker if (ret != EVT_HANDLED_ALL) { 73386470930SIngo Molnar attrs[nr_counters] = attr; 73486470930SIngo Molnar nr_counters++; 735bcd3279fSFrederic Weisbecker } 73686470930SIngo Molnar 73761c45981SPaul Mackerras if (*str == 0) 73861c45981SPaul Mackerras break; 73961c45981SPaul Mackerras if (*str == ',') 74061c45981SPaul Mackerras ++str; 74161c45981SPaul Mackerras while (isspace(*str)) 74261c45981SPaul Mackerras ++str; 74386470930SIngo Molnar } 74486470930SIngo Molnar 74586470930SIngo Molnar return 0; 74686470930SIngo Molnar } 74786470930SIngo Molnar 74886470930SIngo Molnar static const char * const event_type_descriptors[] = { 74986470930SIngo Molnar "", 75086470930SIngo Molnar "Hardware event", 75186470930SIngo Molnar "Software event", 75286470930SIngo Molnar "Tracepoint event", 75386470930SIngo Molnar "Hardware cache event", 75486470930SIngo Molnar }; 75586470930SIngo Molnar 75686470930SIngo Molnar /* 757f6bdafefSJason Baron * Print the events from <debugfs_mount_point>/tracing/events 758f6bdafefSJason Baron */ 759f6bdafefSJason Baron 760f6bdafefSJason Baron static void print_tracepoint_events(void) 761f6bdafefSJason Baron { 762f6bdafefSJason Baron DIR *sys_dir, *evt_dir; 763f6bdafefSJason Baron struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 764f6bdafefSJason Baron char evt_path[MAXPATHLEN]; 765725b1368SEric Dumazet char dir_path[MAXPATHLEN]; 766f6bdafefSJason Baron 7675beeded1SJason Baron if (valid_debugfs_mount(debugfs_path)) 768f6bdafefSJason Baron return; 769f6bdafefSJason Baron 7705beeded1SJason Baron sys_dir = opendir(debugfs_path); 771f6bdafefSJason Baron if (!sys_dir) 772725b1368SEric Dumazet return; 773f6bdafefSJason Baron 7746b58e7f1SUlrich Drepper for_each_subsystem(sys_dir, sys_dirent, sys_next) { 775725b1368SEric Dumazet 776725b1368SEric Dumazet snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 777725b1368SEric Dumazet sys_dirent.d_name); 778725b1368SEric Dumazet evt_dir = opendir(dir_path); 779725b1368SEric Dumazet if (!evt_dir) 7806b58e7f1SUlrich Drepper continue; 781725b1368SEric Dumazet 7826b58e7f1SUlrich Drepper for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 783f6bdafefSJason Baron snprintf(evt_path, MAXPATHLEN, "%s:%s", 784f6bdafefSJason Baron sys_dirent.d_name, evt_dirent.d_name); 78548c2e17fSJason Baron fprintf(stderr, " %-42s [%s]\n", evt_path, 786f6bdafefSJason Baron event_type_descriptors[PERF_TYPE_TRACEPOINT+1]); 787f6bdafefSJason Baron } 788f6bdafefSJason Baron closedir(evt_dir); 789f6bdafefSJason Baron } 790f6bdafefSJason Baron closedir(sys_dir); 791f6bdafefSJason Baron } 792f6bdafefSJason Baron 793f6bdafefSJason Baron /* 79486470930SIngo Molnar * Print the help text for the event symbols: 79586470930SIngo Molnar */ 79686470930SIngo Molnar void print_events(void) 79786470930SIngo Molnar { 79886470930SIngo Molnar struct event_symbol *syms = event_symbols; 79973c24cb8SJaswinder Singh Rajput unsigned int i, type, op, prev_type = -1; 80074d5b588SJaswinder Singh Rajput char name[40]; 80186470930SIngo Molnar 80286470930SIngo Molnar fprintf(stderr, "\n"); 80386470930SIngo Molnar fprintf(stderr, "List of pre-defined events (to be used in -e):\n"); 80486470930SIngo Molnar 80586470930SIngo Molnar for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 80686470930SIngo Molnar type = syms->type + 1; 80723cdb5d5SRoel Kluin if (type >= ARRAY_SIZE(event_type_descriptors)) 80886470930SIngo Molnar type = 0; 80986470930SIngo Molnar 81086470930SIngo Molnar if (type != prev_type) 81186470930SIngo Molnar fprintf(stderr, "\n"); 81286470930SIngo Molnar 81374d5b588SJaswinder Singh Rajput if (strlen(syms->alias)) 81474d5b588SJaswinder Singh Rajput sprintf(name, "%s OR %s", syms->symbol, syms->alias); 81574d5b588SJaswinder Singh Rajput else 81674d5b588SJaswinder Singh Rajput strcpy(name, syms->symbol); 81748c2e17fSJason Baron fprintf(stderr, " %-42s [%s]\n", name, 81886470930SIngo Molnar event_type_descriptors[type]); 81986470930SIngo Molnar 82086470930SIngo Molnar prev_type = type; 82186470930SIngo Molnar } 82286470930SIngo Molnar 82386470930SIngo Molnar fprintf(stderr, "\n"); 82473c24cb8SJaswinder Singh Rajput for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 82573c24cb8SJaswinder Singh Rajput for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 82673c24cb8SJaswinder Singh Rajput /* skip invalid cache type */ 82773c24cb8SJaswinder Singh Rajput if (!is_cache_op_valid(type, op)) 82873c24cb8SJaswinder Singh Rajput continue; 82973c24cb8SJaswinder Singh Rajput 83073c24cb8SJaswinder Singh Rajput for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { 83148c2e17fSJason Baron fprintf(stderr, " %-42s [%s]\n", 83273c24cb8SJaswinder Singh Rajput event_cache_name(type, op, i), 83373c24cb8SJaswinder Singh Rajput event_type_descriptors[4]); 83473c24cb8SJaswinder Singh Rajput } 83573c24cb8SJaswinder Singh Rajput } 83673c24cb8SJaswinder Singh Rajput } 83773c24cb8SJaswinder Singh Rajput 83873c24cb8SJaswinder Singh Rajput fprintf(stderr, "\n"); 83948c2e17fSJason Baron fprintf(stderr, " %-42s [raw hardware event descriptor]\n", 84086470930SIngo Molnar "rNNN"); 84186470930SIngo Molnar fprintf(stderr, "\n"); 84286470930SIngo Molnar 843f6bdafefSJason Baron print_tracepoint_events(); 844f6bdafefSJason Baron 84586470930SIngo Molnar exit(129); 84686470930SIngo Molnar } 847