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 13*cdd6c482SIngo 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 51*cdd6c482SIngo Molnar #define __PERF_EVENT_FIELD(config, name) \ 52*cdd6c482SIngo Molnar ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT) 5386470930SIngo Molnar 54*cdd6c482SIngo Molnar #define PERF_EVENT_RAW(config) __PERF_EVENT_FIELD(config, RAW) 55*cdd6c482SIngo Molnar #define PERF_EVENT_CONFIG(config) __PERF_EVENT_FIELD(config, CONFIG) 56*cdd6c482SIngo Molnar #define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE) 57*cdd6c482SIngo 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]; 1686b58e7f1SUlrich Drepper int sys_dir_fd, fd; 169f6bdafefSJason Baron u64 id; 170f6bdafefSJason Baron char evt_path[MAXPATHLEN]; 171f6bdafefSJason Baron 1725beeded1SJason Baron if (valid_debugfs_mount(debugfs_path)) 1731ef2ed10SFrederic Weisbecker return NULL; 174f6bdafefSJason Baron 1755beeded1SJason Baron sys_dir = opendir(debugfs_path); 176f6bdafefSJason Baron if (!sys_dir) 177f6bdafefSJason Baron goto cleanup; 1786b58e7f1SUlrich Drepper sys_dir_fd = dirfd(sys_dir); 179f6bdafefSJason Baron 1806b58e7f1SUlrich Drepper for_each_subsystem(sys_dir, sys_dirent, sys_next) { 1816b58e7f1SUlrich Drepper int dfd = openat(sys_dir_fd, sys_dirent.d_name, 1826b58e7f1SUlrich Drepper O_RDONLY|O_DIRECTORY), evt_dir_fd; 1836b58e7f1SUlrich Drepper if (dfd == -1) 1846b58e7f1SUlrich Drepper continue; 1856b58e7f1SUlrich Drepper evt_dir = fdopendir(dfd); 1866b58e7f1SUlrich Drepper if (!evt_dir) { 1876b58e7f1SUlrich Drepper close(dfd); 1886b58e7f1SUlrich Drepper continue; 1896b58e7f1SUlrich Drepper } 1906b58e7f1SUlrich Drepper evt_dir_fd = dirfd(evt_dir); 1916b58e7f1SUlrich Drepper for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 1926b58e7f1SUlrich Drepper snprintf(evt_path, MAXPATHLEN, "%s/id", 193f6bdafefSJason Baron evt_dirent.d_name); 1946b58e7f1SUlrich Drepper fd = openat(evt_dir_fd, evt_path, O_RDONLY); 195f6bdafefSJason Baron if (fd < 0) 196f6bdafefSJason Baron continue; 197f6bdafefSJason Baron if (read(fd, id_buf, sizeof(id_buf)) < 0) { 198f6bdafefSJason Baron close(fd); 199f6bdafefSJason Baron continue; 200f6bdafefSJason Baron } 201f6bdafefSJason Baron close(fd); 202f6bdafefSJason Baron id = atoll(id_buf); 203f6bdafefSJason Baron if (id == config) { 204f6bdafefSJason Baron closedir(evt_dir); 205f6bdafefSJason Baron closedir(sys_dir); 2061ef2ed10SFrederic Weisbecker path = calloc(1, sizeof(path)); 2071ef2ed10SFrederic Weisbecker path->system = malloc(MAX_EVENT_LENGTH); 2081ef2ed10SFrederic Weisbecker if (!path->system) { 2091ef2ed10SFrederic Weisbecker free(path); 2101ef2ed10SFrederic Weisbecker return NULL; 2111ef2ed10SFrederic Weisbecker } 2121ef2ed10SFrederic Weisbecker path->name = malloc(MAX_EVENT_LENGTH); 2131ef2ed10SFrederic Weisbecker if (!path->name) { 2141ef2ed10SFrederic Weisbecker free(path->system); 2151ef2ed10SFrederic Weisbecker free(path); 2161ef2ed10SFrederic Weisbecker return NULL; 2171ef2ed10SFrederic Weisbecker } 2181ef2ed10SFrederic Weisbecker strncpy(path->system, sys_dirent.d_name, 2191ef2ed10SFrederic Weisbecker MAX_EVENT_LENGTH); 2201ef2ed10SFrederic Weisbecker strncpy(path->name, evt_dirent.d_name, 2211ef2ed10SFrederic Weisbecker MAX_EVENT_LENGTH); 2221ef2ed10SFrederic Weisbecker return path; 223f6bdafefSJason Baron } 224f6bdafefSJason Baron } 225f6bdafefSJason Baron closedir(evt_dir); 226f6bdafefSJason Baron } 227f6bdafefSJason Baron 228f6bdafefSJason Baron cleanup: 229f6bdafefSJason Baron closedir(sys_dir); 2301ef2ed10SFrederic Weisbecker return NULL; 2311ef2ed10SFrederic Weisbecker } 2321ef2ed10SFrederic Weisbecker 2331ef2ed10SFrederic Weisbecker #define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1) 2341ef2ed10SFrederic Weisbecker static const char *tracepoint_id_to_name(u64 config) 2351ef2ed10SFrederic Weisbecker { 2361ef2ed10SFrederic Weisbecker static char buf[TP_PATH_LEN]; 2371ef2ed10SFrederic Weisbecker struct tracepoint_path *path; 2381ef2ed10SFrederic Weisbecker 2391ef2ed10SFrederic Weisbecker path = tracepoint_id_to_path(config); 2401ef2ed10SFrederic Weisbecker if (path) { 2411ef2ed10SFrederic Weisbecker snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name); 2421ef2ed10SFrederic Weisbecker free(path->name); 2431ef2ed10SFrederic Weisbecker free(path->system); 2441ef2ed10SFrederic Weisbecker free(path); 2451ef2ed10SFrederic Weisbecker } else 2461ef2ed10SFrederic Weisbecker snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown"); 2471ef2ed10SFrederic Weisbecker 2481ef2ed10SFrederic Weisbecker return buf; 249f6bdafefSJason Baron } 250f6bdafefSJason Baron 25106813f6cSJaswinder Singh Rajput static int is_cache_op_valid(u8 cache_type, u8 cache_op) 25206813f6cSJaswinder Singh Rajput { 25306813f6cSJaswinder Singh Rajput if (hw_cache_stat[cache_type] & COP(cache_op)) 25406813f6cSJaswinder Singh Rajput return 1; /* valid */ 25506813f6cSJaswinder Singh Rajput else 25606813f6cSJaswinder Singh Rajput return 0; /* invalid */ 25706813f6cSJaswinder Singh Rajput } 25806813f6cSJaswinder Singh Rajput 259e5c59547SJaswinder Singh Rajput static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result) 260e5c59547SJaswinder Singh Rajput { 261e5c59547SJaswinder Singh Rajput static char name[50]; 262e5c59547SJaswinder Singh Rajput 263e5c59547SJaswinder Singh Rajput if (cache_result) { 264e5c59547SJaswinder Singh Rajput sprintf(name, "%s-%s-%s", hw_cache[cache_type][0], 265e5c59547SJaswinder Singh Rajput hw_cache_op[cache_op][0], 266e5c59547SJaswinder Singh Rajput hw_cache_result[cache_result][0]); 267e5c59547SJaswinder Singh Rajput } else { 268e5c59547SJaswinder Singh Rajput sprintf(name, "%s-%s", hw_cache[cache_type][0], 269e5c59547SJaswinder Singh Rajput hw_cache_op[cache_op][1]); 270e5c59547SJaswinder Singh Rajput } 271e5c59547SJaswinder Singh Rajput 272e5c59547SJaswinder Singh Rajput return name; 273e5c59547SJaswinder Singh Rajput } 274e5c59547SJaswinder Singh Rajput 27583a0944fSIngo Molnar const char *event_name(int counter) 27686470930SIngo Molnar { 2779cffa8d5SPaul Mackerras u64 config = attrs[counter].config; 27886470930SIngo Molnar int type = attrs[counter].type; 2798f18aec5SPeter Zijlstra 2808f18aec5SPeter Zijlstra return __event_name(type, config); 2818f18aec5SPeter Zijlstra } 2828f18aec5SPeter Zijlstra 28383a0944fSIngo Molnar const char *__event_name(int type, u64 config) 2848f18aec5SPeter Zijlstra { 28586470930SIngo Molnar static char buf[32]; 28686470930SIngo Molnar 2878f18aec5SPeter Zijlstra if (type == PERF_TYPE_RAW) { 28886470930SIngo Molnar sprintf(buf, "raw 0x%llx", config); 28986470930SIngo Molnar return buf; 29086470930SIngo Molnar } 29186470930SIngo Molnar 29286470930SIngo Molnar switch (type) { 29386470930SIngo Molnar case PERF_TYPE_HARDWARE: 294f4dbfa8fSPeter Zijlstra if (config < PERF_COUNT_HW_MAX) 29586470930SIngo Molnar return hw_event_names[config]; 29686470930SIngo Molnar return "unknown-hardware"; 29786470930SIngo Molnar 29886470930SIngo Molnar case PERF_TYPE_HW_CACHE: { 2999cffa8d5SPaul Mackerras u8 cache_type, cache_op, cache_result; 30086470930SIngo Molnar 30186470930SIngo Molnar cache_type = (config >> 0) & 0xff; 30286470930SIngo Molnar if (cache_type > PERF_COUNT_HW_CACHE_MAX) 30386470930SIngo Molnar return "unknown-ext-hardware-cache-type"; 30486470930SIngo Molnar 30586470930SIngo Molnar cache_op = (config >> 8) & 0xff; 30686470930SIngo Molnar if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX) 30786470930SIngo Molnar return "unknown-ext-hardware-cache-op"; 30886470930SIngo Molnar 30986470930SIngo Molnar cache_result = (config >> 16) & 0xff; 31086470930SIngo Molnar if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX) 31186470930SIngo Molnar return "unknown-ext-hardware-cache-result"; 31286470930SIngo Molnar 31306813f6cSJaswinder Singh Rajput if (!is_cache_op_valid(cache_type, cache_op)) 31406813f6cSJaswinder Singh Rajput return "invalid-cache"; 31586470930SIngo Molnar 316e5c59547SJaswinder Singh Rajput return event_cache_name(cache_type, cache_op, cache_result); 31786470930SIngo Molnar } 31886470930SIngo Molnar 31986470930SIngo Molnar case PERF_TYPE_SOFTWARE: 320f4dbfa8fSPeter Zijlstra if (config < PERF_COUNT_SW_MAX) 32186470930SIngo Molnar return sw_event_names[config]; 32286470930SIngo Molnar return "unknown-software"; 32386470930SIngo Molnar 324f6bdafefSJason Baron case PERF_TYPE_TRACEPOINT: 325f6bdafefSJason Baron return tracepoint_id_to_name(config); 326f6bdafefSJason Baron 32786470930SIngo Molnar default: 32886470930SIngo Molnar break; 32986470930SIngo Molnar } 33086470930SIngo Molnar 33186470930SIngo Molnar return "unknown"; 33286470930SIngo Molnar } 33386470930SIngo Molnar 33483a0944fSIngo Molnar static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size) 33586470930SIngo Molnar { 33686470930SIngo Molnar int i, j; 33761c45981SPaul Mackerras int n, longest = -1; 33886470930SIngo Molnar 33986470930SIngo Molnar for (i = 0; i < size; i++) { 34061c45981SPaul Mackerras for (j = 0; j < MAX_ALIASES && names[i][j]; j++) { 34161c45981SPaul Mackerras n = strlen(names[i][j]); 34261c45981SPaul Mackerras if (n > longest && !strncasecmp(*str, names[i][j], n)) 34361c45981SPaul Mackerras longest = n; 34461c45981SPaul Mackerras } 34561c45981SPaul Mackerras if (longest > 0) { 34661c45981SPaul Mackerras *str += longest; 34786470930SIngo Molnar return i; 34886470930SIngo Molnar } 34986470930SIngo Molnar } 35086470930SIngo Molnar 3518953645fSIngo Molnar return -1; 35286470930SIngo Molnar } 35386470930SIngo Molnar 354bcd3279fSFrederic Weisbecker static enum event_result 355*cdd6c482SIngo Molnar parse_generic_hw_event(const char **str, struct perf_event_attr *attr) 35686470930SIngo Molnar { 35761c45981SPaul Mackerras const char *s = *str; 35861c45981SPaul Mackerras int cache_type = -1, cache_op = -1, cache_result = -1; 35986470930SIngo Molnar 36061c45981SPaul Mackerras cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX); 36186470930SIngo Molnar /* 36286470930SIngo Molnar * No fallback - if we cannot get a clear cache type 36386470930SIngo Molnar * then bail out: 36486470930SIngo Molnar */ 36586470930SIngo Molnar if (cache_type == -1) 366bcd3279fSFrederic Weisbecker return EVT_FAILED; 36786470930SIngo Molnar 36861c45981SPaul Mackerras while ((cache_op == -1 || cache_result == -1) && *s == '-') { 36961c45981SPaul Mackerras ++s; 37061c45981SPaul Mackerras 37161c45981SPaul Mackerras if (cache_op == -1) { 37261c45981SPaul Mackerras cache_op = parse_aliases(&s, hw_cache_op, 37361c45981SPaul Mackerras PERF_COUNT_HW_CACHE_OP_MAX); 37461c45981SPaul Mackerras if (cache_op >= 0) { 37561c45981SPaul Mackerras if (!is_cache_op_valid(cache_type, cache_op)) 37661c45981SPaul Mackerras return 0; 37761c45981SPaul Mackerras continue; 37861c45981SPaul Mackerras } 37961c45981SPaul Mackerras } 38061c45981SPaul Mackerras 38161c45981SPaul Mackerras if (cache_result == -1) { 38261c45981SPaul Mackerras cache_result = parse_aliases(&s, hw_cache_result, 38361c45981SPaul Mackerras PERF_COUNT_HW_CACHE_RESULT_MAX); 38461c45981SPaul Mackerras if (cache_result >= 0) 38561c45981SPaul Mackerras continue; 38661c45981SPaul Mackerras } 38761c45981SPaul Mackerras 38861c45981SPaul Mackerras /* 38961c45981SPaul Mackerras * Can't parse this as a cache op or result, so back up 39061c45981SPaul Mackerras * to the '-'. 39161c45981SPaul Mackerras */ 39261c45981SPaul Mackerras --s; 39361c45981SPaul Mackerras break; 39461c45981SPaul Mackerras } 39561c45981SPaul Mackerras 39686470930SIngo Molnar /* 39786470930SIngo Molnar * Fall back to reads: 39886470930SIngo Molnar */ 3998953645fSIngo Molnar if (cache_op == -1) 4008953645fSIngo Molnar cache_op = PERF_COUNT_HW_CACHE_OP_READ; 40186470930SIngo Molnar 40286470930SIngo Molnar /* 40386470930SIngo Molnar * Fall back to accesses: 40486470930SIngo Molnar */ 40586470930SIngo Molnar if (cache_result == -1) 40686470930SIngo Molnar cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS; 40786470930SIngo Molnar 40886470930SIngo Molnar attr->config = cache_type | (cache_op << 8) | (cache_result << 16); 40986470930SIngo Molnar attr->type = PERF_TYPE_HW_CACHE; 41086470930SIngo Molnar 41161c45981SPaul Mackerras *str = s; 412bcd3279fSFrederic Weisbecker return EVT_HANDLED; 41386470930SIngo Molnar } 41486470930SIngo Molnar 415bcd3279fSFrederic Weisbecker static enum event_result 416bcd3279fSFrederic Weisbecker parse_single_tracepoint_event(char *sys_name, 417bcd3279fSFrederic Weisbecker const char *evt_name, 418bcd3279fSFrederic Weisbecker unsigned int evt_length, 419bcd3279fSFrederic Weisbecker char *flags, 420*cdd6c482SIngo Molnar struct perf_event_attr *attr, 421bcd3279fSFrederic Weisbecker const char **strp) 422bcd3279fSFrederic Weisbecker { 423bcd3279fSFrederic Weisbecker char evt_path[MAXPATHLEN]; 424bcd3279fSFrederic Weisbecker char id_buf[4]; 425bcd3279fSFrederic Weisbecker u64 id; 426bcd3279fSFrederic Weisbecker int fd; 427bcd3279fSFrederic Weisbecker 428bcd3279fSFrederic Weisbecker if (flags) { 4291281a49bSLi Zefan if (!strncmp(flags, "record", strlen(flags))) { 430bcd3279fSFrederic Weisbecker attr->sample_type |= PERF_SAMPLE_RAW; 4311281a49bSLi Zefan attr->sample_type |= PERF_SAMPLE_TIME; 4321281a49bSLi Zefan attr->sample_type |= PERF_SAMPLE_CPU; 4331281a49bSLi Zefan } 434bcd3279fSFrederic Weisbecker } 435bcd3279fSFrederic Weisbecker 436bcd3279fSFrederic Weisbecker snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 437bcd3279fSFrederic Weisbecker sys_name, evt_name); 438bcd3279fSFrederic Weisbecker 439bcd3279fSFrederic Weisbecker fd = open(evt_path, O_RDONLY); 440bcd3279fSFrederic Weisbecker if (fd < 0) 441bcd3279fSFrederic Weisbecker return EVT_FAILED; 442bcd3279fSFrederic Weisbecker 443bcd3279fSFrederic Weisbecker if (read(fd, id_buf, sizeof(id_buf)) < 0) { 444bcd3279fSFrederic Weisbecker close(fd); 445bcd3279fSFrederic Weisbecker return EVT_FAILED; 446bcd3279fSFrederic Weisbecker } 447bcd3279fSFrederic Weisbecker 448bcd3279fSFrederic Weisbecker close(fd); 449bcd3279fSFrederic Weisbecker id = atoll(id_buf); 450bcd3279fSFrederic Weisbecker attr->config = id; 451bcd3279fSFrederic Weisbecker attr->type = PERF_TYPE_TRACEPOINT; 452bcd3279fSFrederic Weisbecker *strp = evt_name + evt_length; 453bcd3279fSFrederic Weisbecker 454bcd3279fSFrederic Weisbecker return EVT_HANDLED; 455bcd3279fSFrederic Weisbecker } 456bcd3279fSFrederic Weisbecker 457bcd3279fSFrederic Weisbecker /* sys + ':' + event + ':' + flags*/ 458bcd3279fSFrederic Weisbecker #define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128) 459bcd3279fSFrederic Weisbecker static enum event_result 460bcd3279fSFrederic Weisbecker parse_subsystem_tracepoint_event(char *sys_name, char *flags) 461bcd3279fSFrederic Weisbecker { 462bcd3279fSFrederic Weisbecker char evt_path[MAXPATHLEN]; 463bcd3279fSFrederic Weisbecker struct dirent *evt_ent; 464bcd3279fSFrederic Weisbecker DIR *evt_dir; 465bcd3279fSFrederic Weisbecker 466bcd3279fSFrederic Weisbecker snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name); 467bcd3279fSFrederic Weisbecker evt_dir = opendir(evt_path); 468bcd3279fSFrederic Weisbecker 469bcd3279fSFrederic Weisbecker if (!evt_dir) { 470bcd3279fSFrederic Weisbecker perror("Can't open event dir"); 471bcd3279fSFrederic Weisbecker return EVT_FAILED; 472bcd3279fSFrederic Weisbecker } 473bcd3279fSFrederic Weisbecker 474bcd3279fSFrederic Weisbecker while ((evt_ent = readdir(evt_dir))) { 475bcd3279fSFrederic Weisbecker char event_opt[MAX_EVOPT_LEN + 1]; 476bcd3279fSFrederic Weisbecker int len; 477bcd3279fSFrederic Weisbecker unsigned int rem = MAX_EVOPT_LEN; 478bcd3279fSFrederic Weisbecker 479bcd3279fSFrederic Weisbecker if (!strcmp(evt_ent->d_name, ".") 480bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "..") 481bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "enable") 482bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "filter")) 483bcd3279fSFrederic Weisbecker continue; 484bcd3279fSFrederic Weisbecker 485bcd3279fSFrederic Weisbecker len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s", sys_name, 486bcd3279fSFrederic Weisbecker evt_ent->d_name); 487bcd3279fSFrederic Weisbecker if (len < 0) 488bcd3279fSFrederic Weisbecker return EVT_FAILED; 489bcd3279fSFrederic Weisbecker 490bcd3279fSFrederic Weisbecker rem -= len; 491bcd3279fSFrederic Weisbecker if (flags) { 492bcd3279fSFrederic Weisbecker if (rem < strlen(flags) + 1) 493bcd3279fSFrederic Weisbecker return EVT_FAILED; 494bcd3279fSFrederic Weisbecker 495bcd3279fSFrederic Weisbecker strcat(event_opt, ":"); 496bcd3279fSFrederic Weisbecker strcat(event_opt, flags); 497bcd3279fSFrederic Weisbecker } 498bcd3279fSFrederic Weisbecker 499bcd3279fSFrederic Weisbecker if (parse_events(NULL, event_opt, 0)) 500bcd3279fSFrederic Weisbecker return EVT_FAILED; 501bcd3279fSFrederic Weisbecker } 502bcd3279fSFrederic Weisbecker 503bcd3279fSFrederic Weisbecker return EVT_HANDLED_ALL; 504bcd3279fSFrederic Weisbecker } 505bcd3279fSFrederic Weisbecker 506bcd3279fSFrederic Weisbecker 507bcd3279fSFrederic Weisbecker static enum event_result parse_tracepoint_event(const char **strp, 508*cdd6c482SIngo Molnar struct perf_event_attr *attr) 509f6bdafefSJason Baron { 510f6bdafefSJason Baron const char *evt_name; 5113a9f131fSFrederic Weisbecker char *flags; 512f6bdafefSJason Baron char sys_name[MAX_EVENT_LENGTH]; 513f6bdafefSJason Baron unsigned int sys_length, evt_length; 514f6bdafefSJason Baron 5155beeded1SJason Baron if (valid_debugfs_mount(debugfs_path)) 516f6bdafefSJason Baron return 0; 517f6bdafefSJason Baron 518f6bdafefSJason Baron evt_name = strchr(*strp, ':'); 519f6bdafefSJason Baron if (!evt_name) 520bcd3279fSFrederic Weisbecker return EVT_FAILED; 521f6bdafefSJason Baron 522f6bdafefSJason Baron sys_length = evt_name - *strp; 523f6bdafefSJason Baron if (sys_length >= MAX_EVENT_LENGTH) 524f6bdafefSJason Baron return 0; 525f6bdafefSJason Baron 526f6bdafefSJason Baron strncpy(sys_name, *strp, sys_length); 527f6bdafefSJason Baron sys_name[sys_length] = '\0'; 528f6bdafefSJason Baron evt_name = evt_name + 1; 5293a9f131fSFrederic Weisbecker 5303a9f131fSFrederic Weisbecker flags = strchr(evt_name, ':'); 5313a9f131fSFrederic Weisbecker if (flags) { 5321fc35b29SIngo Molnar /* split it out: */ 5331fc35b29SIngo Molnar evt_name = strndup(evt_name, flags - evt_name); 5343a9f131fSFrederic Weisbecker flags++; 5353a9f131fSFrederic Weisbecker } 5363a9f131fSFrederic Weisbecker 537f6bdafefSJason Baron evt_length = strlen(evt_name); 538f6bdafefSJason Baron if (evt_length >= MAX_EVENT_LENGTH) 539bcd3279fSFrederic Weisbecker return EVT_FAILED; 540f6bdafefSJason Baron 541bcd3279fSFrederic Weisbecker if (!strcmp(evt_name, "*")) { 542f6bdafefSJason Baron *strp = evt_name + evt_length; 543bcd3279fSFrederic Weisbecker return parse_subsystem_tracepoint_event(sys_name, flags); 544bcd3279fSFrederic Weisbecker } else 545bcd3279fSFrederic Weisbecker return parse_single_tracepoint_event(sys_name, evt_name, 546bcd3279fSFrederic Weisbecker evt_length, flags, 547bcd3279fSFrederic Weisbecker attr, strp); 548f6bdafefSJason Baron } 549f6bdafefSJason Baron 55074d5b588SJaswinder Singh Rajput static int check_events(const char *str, unsigned int i) 55174d5b588SJaswinder Singh Rajput { 55261c45981SPaul Mackerras int n; 55374d5b588SJaswinder Singh Rajput 55461c45981SPaul Mackerras n = strlen(event_symbols[i].symbol); 55561c45981SPaul Mackerras if (!strncmp(str, event_symbols[i].symbol, n)) 55661c45981SPaul Mackerras return n; 55761c45981SPaul Mackerras 55861c45981SPaul Mackerras n = strlen(event_symbols[i].alias); 55961c45981SPaul Mackerras if (n) 56061c45981SPaul Mackerras if (!strncmp(str, event_symbols[i].alias, n)) 56161c45981SPaul Mackerras return n; 56261c45981SPaul Mackerras return 0; 56361c45981SPaul Mackerras } 56461c45981SPaul Mackerras 565bcd3279fSFrederic Weisbecker static enum event_result 566*cdd6c482SIngo Molnar parse_symbolic_event(const char **strp, struct perf_event_attr *attr) 56761c45981SPaul Mackerras { 56861c45981SPaul Mackerras const char *str = *strp; 56961c45981SPaul Mackerras unsigned int i; 57061c45981SPaul Mackerras int n; 57161c45981SPaul Mackerras 57261c45981SPaul Mackerras for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { 57361c45981SPaul Mackerras n = check_events(str, i); 57461c45981SPaul Mackerras if (n > 0) { 57561c45981SPaul Mackerras attr->type = event_symbols[i].type; 57661c45981SPaul Mackerras attr->config = event_symbols[i].config; 57761c45981SPaul Mackerras *strp = str + n; 578bcd3279fSFrederic Weisbecker return EVT_HANDLED; 57961c45981SPaul Mackerras } 58061c45981SPaul Mackerras } 581bcd3279fSFrederic Weisbecker return EVT_FAILED; 58261c45981SPaul Mackerras } 58361c45981SPaul Mackerras 584bcd3279fSFrederic Weisbecker static enum event_result 585*cdd6c482SIngo Molnar parse_raw_event(const char **strp, struct perf_event_attr *attr) 58661c45981SPaul Mackerras { 58761c45981SPaul Mackerras const char *str = *strp; 58861c45981SPaul Mackerras u64 config; 58961c45981SPaul Mackerras int n; 59061c45981SPaul Mackerras 59161c45981SPaul Mackerras if (*str != 'r') 592bcd3279fSFrederic Weisbecker return EVT_FAILED; 59361c45981SPaul Mackerras n = hex2u64(str + 1, &config); 59461c45981SPaul Mackerras if (n > 0) { 59561c45981SPaul Mackerras *strp = str + n + 1; 59661c45981SPaul Mackerras attr->type = PERF_TYPE_RAW; 59761c45981SPaul Mackerras attr->config = config; 598bcd3279fSFrederic Weisbecker return EVT_HANDLED; 59961c45981SPaul Mackerras } 600bcd3279fSFrederic Weisbecker return EVT_FAILED; 60161c45981SPaul Mackerras } 60261c45981SPaul Mackerras 603bcd3279fSFrederic Weisbecker static enum event_result 604*cdd6c482SIngo Molnar parse_numeric_event(const char **strp, struct perf_event_attr *attr) 60561c45981SPaul Mackerras { 60661c45981SPaul Mackerras const char *str = *strp; 60761c45981SPaul Mackerras char *endp; 60861c45981SPaul Mackerras unsigned long type; 60961c45981SPaul Mackerras u64 config; 61061c45981SPaul Mackerras 61161c45981SPaul Mackerras type = strtoul(str, &endp, 0); 61261c45981SPaul Mackerras if (endp > str && type < PERF_TYPE_MAX && *endp == ':') { 61361c45981SPaul Mackerras str = endp + 1; 61461c45981SPaul Mackerras config = strtoul(str, &endp, 0); 61561c45981SPaul Mackerras if (endp > str) { 61661c45981SPaul Mackerras attr->type = type; 61761c45981SPaul Mackerras attr->config = config; 61861c45981SPaul Mackerras *strp = endp; 619bcd3279fSFrederic Weisbecker return EVT_HANDLED; 62061c45981SPaul Mackerras } 62161c45981SPaul Mackerras } 622bcd3279fSFrederic Weisbecker return EVT_FAILED; 62361c45981SPaul Mackerras } 62461c45981SPaul Mackerras 625bcd3279fSFrederic Weisbecker static enum event_result 626*cdd6c482SIngo Molnar parse_event_modifier(const char **strp, struct perf_event_attr *attr) 62761c45981SPaul Mackerras { 62861c45981SPaul Mackerras const char *str = *strp; 62961c45981SPaul Mackerras int eu = 1, ek = 1, eh = 1; 63061c45981SPaul Mackerras 63161c45981SPaul Mackerras if (*str++ != ':') 63261c45981SPaul Mackerras return 0; 63361c45981SPaul Mackerras while (*str) { 63461c45981SPaul Mackerras if (*str == 'u') 63561c45981SPaul Mackerras eu = 0; 63661c45981SPaul Mackerras else if (*str == 'k') 63761c45981SPaul Mackerras ek = 0; 63861c45981SPaul Mackerras else if (*str == 'h') 63961c45981SPaul Mackerras eh = 0; 64061c45981SPaul Mackerras else 64161c45981SPaul Mackerras break; 64261c45981SPaul Mackerras ++str; 64361c45981SPaul Mackerras } 64461c45981SPaul Mackerras if (str >= *strp + 2) { 64561c45981SPaul Mackerras *strp = str; 64661c45981SPaul Mackerras attr->exclude_user = eu; 64761c45981SPaul Mackerras attr->exclude_kernel = ek; 64861c45981SPaul Mackerras attr->exclude_hv = eh; 64961c45981SPaul Mackerras return 1; 65061c45981SPaul Mackerras } 65174d5b588SJaswinder Singh Rajput return 0; 65274d5b588SJaswinder Singh Rajput } 65374d5b588SJaswinder Singh Rajput 65486470930SIngo Molnar /* 65586470930SIngo Molnar * Each event can have multiple symbolic names. 65686470930SIngo Molnar * Symbolic names are (almost) exactly matched. 65786470930SIngo Molnar */ 658bcd3279fSFrederic Weisbecker static enum event_result 659*cdd6c482SIngo Molnar parse_event_symbols(const char **str, struct perf_event_attr *attr) 66086470930SIngo Molnar { 661bcd3279fSFrederic Weisbecker enum event_result ret; 66286470930SIngo Molnar 663bcd3279fSFrederic Weisbecker ret = parse_tracepoint_event(str, attr); 664bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 665bcd3279fSFrederic Weisbecker goto modifier; 666bcd3279fSFrederic Weisbecker 667bcd3279fSFrederic Weisbecker ret = parse_raw_event(str, attr); 668bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 669bcd3279fSFrederic Weisbecker goto modifier; 670bcd3279fSFrederic Weisbecker 671bcd3279fSFrederic Weisbecker ret = parse_numeric_event(str, attr); 672bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 673bcd3279fSFrederic Weisbecker goto modifier; 674bcd3279fSFrederic Weisbecker 675bcd3279fSFrederic Weisbecker ret = parse_symbolic_event(str, attr); 676bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 677bcd3279fSFrederic Weisbecker goto modifier; 678bcd3279fSFrederic Weisbecker 679bcd3279fSFrederic Weisbecker ret = parse_generic_hw_event(str, attr); 680bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 681bcd3279fSFrederic Weisbecker goto modifier; 682bcd3279fSFrederic Weisbecker 683bcd3279fSFrederic Weisbecker return EVT_FAILED; 684bcd3279fSFrederic Weisbecker 685bcd3279fSFrederic Weisbecker modifier: 68661c45981SPaul Mackerras parse_event_modifier(str, attr); 68786470930SIngo Molnar 688bcd3279fSFrederic Weisbecker return ret; 68986470930SIngo Molnar } 69086470930SIngo Molnar 6918755a8f2SArjan van de Ven static void store_event_type(const char *orgname) 6928755a8f2SArjan van de Ven { 6938755a8f2SArjan van de Ven char filename[PATH_MAX], *c; 6948755a8f2SArjan van de Ven FILE *file; 6958755a8f2SArjan van de Ven int id; 6968755a8f2SArjan van de Ven 6978755a8f2SArjan van de Ven sprintf(filename, "/sys/kernel/debug/tracing/events/%s/id", orgname); 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 { 714*cdd6c482SIngo 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; 7646b58e7f1SUlrich Drepper int sys_dir_fd; 765f6bdafefSJason Baron char evt_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) 772f6bdafefSJason Baron goto cleanup; 7736b58e7f1SUlrich Drepper sys_dir_fd = dirfd(sys_dir); 774f6bdafefSJason Baron 7756b58e7f1SUlrich Drepper for_each_subsystem(sys_dir, sys_dirent, sys_next) { 7766b58e7f1SUlrich Drepper int dfd = openat(sys_dir_fd, sys_dirent.d_name, 7776b58e7f1SUlrich Drepper O_RDONLY|O_DIRECTORY), evt_dir_fd; 7786b58e7f1SUlrich Drepper if (dfd == -1) 7796b58e7f1SUlrich Drepper continue; 7806b58e7f1SUlrich Drepper evt_dir = fdopendir(dfd); 7816b58e7f1SUlrich Drepper if (!evt_dir) { 7826b58e7f1SUlrich Drepper close(dfd); 7836b58e7f1SUlrich Drepper continue; 7846b58e7f1SUlrich Drepper } 7856b58e7f1SUlrich Drepper evt_dir_fd = dirfd(evt_dir); 7866b58e7f1SUlrich Drepper for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 787f6bdafefSJason Baron snprintf(evt_path, MAXPATHLEN, "%s:%s", 788f6bdafefSJason Baron sys_dirent.d_name, evt_dirent.d_name); 78948c2e17fSJason Baron fprintf(stderr, " %-42s [%s]\n", evt_path, 790f6bdafefSJason Baron event_type_descriptors[PERF_TYPE_TRACEPOINT+1]); 791f6bdafefSJason Baron } 792f6bdafefSJason Baron closedir(evt_dir); 793f6bdafefSJason Baron } 794f6bdafefSJason Baron 795f6bdafefSJason Baron cleanup: 796f6bdafefSJason Baron closedir(sys_dir); 797f6bdafefSJason Baron } 798f6bdafefSJason Baron 799f6bdafefSJason Baron /* 80086470930SIngo Molnar * Print the help text for the event symbols: 80186470930SIngo Molnar */ 80286470930SIngo Molnar void print_events(void) 80386470930SIngo Molnar { 80486470930SIngo Molnar struct event_symbol *syms = event_symbols; 80573c24cb8SJaswinder Singh Rajput unsigned int i, type, op, prev_type = -1; 80674d5b588SJaswinder Singh Rajput char name[40]; 80786470930SIngo Molnar 80886470930SIngo Molnar fprintf(stderr, "\n"); 80986470930SIngo Molnar fprintf(stderr, "List of pre-defined events (to be used in -e):\n"); 81086470930SIngo Molnar 81186470930SIngo Molnar for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 81286470930SIngo Molnar type = syms->type + 1; 81323cdb5d5SRoel Kluin if (type >= ARRAY_SIZE(event_type_descriptors)) 81486470930SIngo Molnar type = 0; 81586470930SIngo Molnar 81686470930SIngo Molnar if (type != prev_type) 81786470930SIngo Molnar fprintf(stderr, "\n"); 81886470930SIngo Molnar 81974d5b588SJaswinder Singh Rajput if (strlen(syms->alias)) 82074d5b588SJaswinder Singh Rajput sprintf(name, "%s OR %s", syms->symbol, syms->alias); 82174d5b588SJaswinder Singh Rajput else 82274d5b588SJaswinder Singh Rajput strcpy(name, syms->symbol); 82348c2e17fSJason Baron fprintf(stderr, " %-42s [%s]\n", name, 82486470930SIngo Molnar event_type_descriptors[type]); 82586470930SIngo Molnar 82686470930SIngo Molnar prev_type = type; 82786470930SIngo Molnar } 82886470930SIngo Molnar 82986470930SIngo Molnar fprintf(stderr, "\n"); 83073c24cb8SJaswinder Singh Rajput for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 83173c24cb8SJaswinder Singh Rajput for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 83273c24cb8SJaswinder Singh Rajput /* skip invalid cache type */ 83373c24cb8SJaswinder Singh Rajput if (!is_cache_op_valid(type, op)) 83473c24cb8SJaswinder Singh Rajput continue; 83573c24cb8SJaswinder Singh Rajput 83673c24cb8SJaswinder Singh Rajput for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { 83748c2e17fSJason Baron fprintf(stderr, " %-42s [%s]\n", 83873c24cb8SJaswinder Singh Rajput event_cache_name(type, op, i), 83973c24cb8SJaswinder Singh Rajput event_type_descriptors[4]); 84073c24cb8SJaswinder Singh Rajput } 84173c24cb8SJaswinder Singh Rajput } 84273c24cb8SJaswinder Singh Rajput } 84373c24cb8SJaswinder Singh Rajput 84473c24cb8SJaswinder Singh Rajput fprintf(stderr, "\n"); 84548c2e17fSJason Baron fprintf(stderr, " %-42s [raw hardware event descriptor]\n", 84686470930SIngo Molnar "rNNN"); 84786470930SIngo Molnar fprintf(stderr, "\n"); 84886470930SIngo Molnar 849f6bdafefSJason Baron print_tracepoint_events(); 850f6bdafefSJason Baron 85186470930SIngo Molnar exit(129); 85286470930SIngo Molnar } 853