11b290d67SFrederic Weisbecker #include "../../../include/linux/hw_breakpoint.h" 286470930SIngo Molnar #include "util.h" 36b58e7f1SUlrich Drepper #include "../perf.h" 469aad6f1SArnaldo Carvalho de Melo #include "evsel.h" 586470930SIngo Molnar #include "parse-options.h" 686470930SIngo Molnar #include "parse-events.h" 786470930SIngo Molnar #include "exec_cmd.h" 886470930SIngo Molnar #include "string.h" 95aab621bSArnaldo Carvalho de Melo #include "symbol.h" 105beeded1SJason Baron #include "cache.h" 118755a8f2SArjan van de Ven #include "header.h" 12549104f2SClark Williams #include "debugfs.h" 1386470930SIngo Molnar 1486470930SIngo Molnar int nr_counters; 1586470930SIngo Molnar 1669aad6f1SArnaldo Carvalho de Melo LIST_HEAD(evsel_list); 1786470930SIngo Molnar 1886470930SIngo Molnar struct event_symbol { 199cffa8d5SPaul Mackerras u8 type; 209cffa8d5SPaul Mackerras u64 config; 2183a0944fSIngo Molnar const char *symbol; 2283a0944fSIngo Molnar const char *alias; 2386470930SIngo Molnar }; 2486470930SIngo Molnar 25bcd3279fSFrederic Weisbecker enum event_result { 26bcd3279fSFrederic Weisbecker EVT_FAILED, 27bcd3279fSFrederic Weisbecker EVT_HANDLED, 28bcd3279fSFrederic Weisbecker EVT_HANDLED_ALL 29bcd3279fSFrederic Weisbecker }; 30bcd3279fSFrederic Weisbecker 315beeded1SJason Baron char debugfs_path[MAXPATHLEN]; 325beeded1SJason Baron 3351e26842SJaswinder Singh Rajput #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 3451e26842SJaswinder Singh Rajput #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x 3586470930SIngo Molnar 3686470930SIngo Molnar static struct event_symbol event_symbols[] = { 3774d5b588SJaswinder Singh Rajput { CHW(CPU_CYCLES), "cpu-cycles", "cycles" }, 3874d5b588SJaswinder Singh Rajput { CHW(INSTRUCTIONS), "instructions", "" }, 3974d5b588SJaswinder Singh Rajput { CHW(CACHE_REFERENCES), "cache-references", "" }, 4074d5b588SJaswinder Singh Rajput { CHW(CACHE_MISSES), "cache-misses", "" }, 4174d5b588SJaswinder Singh Rajput { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" }, 4274d5b588SJaswinder Singh Rajput { CHW(BRANCH_MISSES), "branch-misses", "" }, 4374d5b588SJaswinder Singh Rajput { CHW(BUS_CYCLES), "bus-cycles", "" }, 4486470930SIngo Molnar 4574d5b588SJaswinder Singh Rajput { CSW(CPU_CLOCK), "cpu-clock", "" }, 4674d5b588SJaswinder Singh Rajput { CSW(TASK_CLOCK), "task-clock", "" }, 47c0c22dbfSJaswinder Singh Rajput { CSW(PAGE_FAULTS), "page-faults", "faults" }, 4874d5b588SJaswinder Singh Rajput { CSW(PAGE_FAULTS_MIN), "minor-faults", "" }, 4974d5b588SJaswinder Singh Rajput { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, 5074d5b588SJaswinder Singh Rajput { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, 5174d5b588SJaswinder Singh Rajput { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, 52f7d79860SAnton Blanchard { CSW(ALIGNMENT_FAULTS), "alignment-faults", "" }, 53f7d79860SAnton Blanchard { CSW(EMULATION_FAULTS), "emulation-faults", "" }, 5486470930SIngo Molnar }; 5586470930SIngo Molnar 56cdd6c482SIngo Molnar #define __PERF_EVENT_FIELD(config, name) \ 57cdd6c482SIngo Molnar ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT) 5886470930SIngo Molnar 59cdd6c482SIngo Molnar #define PERF_EVENT_RAW(config) __PERF_EVENT_FIELD(config, RAW) 60cdd6c482SIngo Molnar #define PERF_EVENT_CONFIG(config) __PERF_EVENT_FIELD(config, CONFIG) 61cdd6c482SIngo Molnar #define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE) 62cdd6c482SIngo Molnar #define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT) 6386470930SIngo Molnar 6483a0944fSIngo Molnar static const char *hw_event_names[] = { 6586470930SIngo Molnar "cycles", 6686470930SIngo Molnar "instructions", 6786470930SIngo Molnar "cache-references", 6886470930SIngo Molnar "cache-misses", 6986470930SIngo Molnar "branches", 7086470930SIngo Molnar "branch-misses", 7186470930SIngo Molnar "bus-cycles", 7286470930SIngo Molnar }; 7386470930SIngo Molnar 7483a0944fSIngo Molnar static const char *sw_event_names[] = { 7544175b6fSIngo Molnar "cpu-clock-msecs", 7644175b6fSIngo Molnar "task-clock-msecs", 7786470930SIngo Molnar "page-faults", 7886470930SIngo Molnar "context-switches", 7986470930SIngo Molnar "CPU-migrations", 8086470930SIngo Molnar "minor-faults", 8186470930SIngo Molnar "major-faults", 82f7d79860SAnton Blanchard "alignment-faults", 83f7d79860SAnton Blanchard "emulation-faults", 8486470930SIngo Molnar }; 8586470930SIngo Molnar 8686470930SIngo Molnar #define MAX_ALIASES 8 8786470930SIngo Molnar 8883a0944fSIngo Molnar static const char *hw_cache[][MAX_ALIASES] = { 899590b7baSAnton Blanchard { "L1-dcache", "l1-d", "l1d", "L1-data", }, 909590b7baSAnton Blanchard { "L1-icache", "l1-i", "l1i", "L1-instruction", }, 91e5c59547SJaswinder Singh Rajput { "LLC", "L2" }, 92e5c59547SJaswinder Singh Rajput { "dTLB", "d-tlb", "Data-TLB", }, 93e5c59547SJaswinder Singh Rajput { "iTLB", "i-tlb", "Instruction-TLB", }, 94e5c59547SJaswinder Singh Rajput { "branch", "branches", "bpu", "btb", "bpc", }, 9586470930SIngo Molnar }; 9686470930SIngo Molnar 9783a0944fSIngo Molnar static const char *hw_cache_op[][MAX_ALIASES] = { 98e5c59547SJaswinder Singh Rajput { "load", "loads", "read", }, 99e5c59547SJaswinder Singh Rajput { "store", "stores", "write", }, 100e5c59547SJaswinder Singh Rajput { "prefetch", "prefetches", "speculative-read", "speculative-load", }, 10186470930SIngo Molnar }; 10286470930SIngo Molnar 10383a0944fSIngo Molnar static const char *hw_cache_result[][MAX_ALIASES] = { 104e5c59547SJaswinder Singh Rajput { "refs", "Reference", "ops", "access", }, 105e5c59547SJaswinder Singh Rajput { "misses", "miss", }, 10686470930SIngo Molnar }; 10786470930SIngo Molnar 10806813f6cSJaswinder Singh Rajput #define C(x) PERF_COUNT_HW_CACHE_##x 10906813f6cSJaswinder Singh Rajput #define CACHE_READ (1 << C(OP_READ)) 11006813f6cSJaswinder Singh Rajput #define CACHE_WRITE (1 << C(OP_WRITE)) 11106813f6cSJaswinder Singh Rajput #define CACHE_PREFETCH (1 << C(OP_PREFETCH)) 11206813f6cSJaswinder Singh Rajput #define COP(x) (1 << x) 11306813f6cSJaswinder Singh Rajput 11406813f6cSJaswinder Singh Rajput /* 11506813f6cSJaswinder Singh Rajput * cache operartion stat 11606813f6cSJaswinder Singh Rajput * L1I : Read and prefetch only 11706813f6cSJaswinder Singh Rajput * ITLB and BPU : Read-only 11806813f6cSJaswinder Singh Rajput */ 11906813f6cSJaswinder Singh Rajput static unsigned long hw_cache_stat[C(MAX)] = { 12006813f6cSJaswinder Singh Rajput [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 12106813f6cSJaswinder Singh Rajput [C(L1I)] = (CACHE_READ | CACHE_PREFETCH), 12206813f6cSJaswinder Singh Rajput [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 12306813f6cSJaswinder Singh Rajput [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 12406813f6cSJaswinder Singh Rajput [C(ITLB)] = (CACHE_READ), 12506813f6cSJaswinder Singh Rajput [C(BPU)] = (CACHE_READ), 12606813f6cSJaswinder Singh Rajput }; 12706813f6cSJaswinder Singh Rajput 1286b58e7f1SUlrich Drepper #define for_each_subsystem(sys_dir, sys_dirent, sys_next) \ 129f6bdafefSJason Baron while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ 1306b58e7f1SUlrich Drepper if (sys_dirent.d_type == DT_DIR && \ 131f6bdafefSJason Baron (strcmp(sys_dirent.d_name, ".")) && \ 132f6bdafefSJason Baron (strcmp(sys_dirent.d_name, ".."))) 133f6bdafefSJason Baron 134ae07b63fSPeter Zijlstra static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir) 135ae07b63fSPeter Zijlstra { 136ae07b63fSPeter Zijlstra char evt_path[MAXPATHLEN]; 137ae07b63fSPeter Zijlstra int fd; 138ae07b63fSPeter Zijlstra 139ae07b63fSPeter Zijlstra snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 140ae07b63fSPeter Zijlstra sys_dir->d_name, evt_dir->d_name); 141ae07b63fSPeter Zijlstra fd = open(evt_path, O_RDONLY); 142ae07b63fSPeter Zijlstra if (fd < 0) 143ae07b63fSPeter Zijlstra return -EINVAL; 144ae07b63fSPeter Zijlstra close(fd); 145ae07b63fSPeter Zijlstra 146ae07b63fSPeter Zijlstra return 0; 147ae07b63fSPeter Zijlstra } 148ae07b63fSPeter Zijlstra 1496b58e7f1SUlrich Drepper #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) \ 150f6bdafefSJason Baron while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \ 1516b58e7f1SUlrich Drepper if (evt_dirent.d_type == DT_DIR && \ 152f6bdafefSJason Baron (strcmp(evt_dirent.d_name, ".")) && \ 153ae07b63fSPeter Zijlstra (strcmp(evt_dirent.d_name, "..")) && \ 154ae07b63fSPeter Zijlstra (!tp_event_has_id(&sys_dirent, &evt_dirent))) 155f6bdafefSJason Baron 156270bbbe8SLi Zefan #define MAX_EVENT_LENGTH 512 157f6bdafefSJason Baron 158f6bdafefSJason Baron 1591ef2ed10SFrederic Weisbecker struct tracepoint_path *tracepoint_id_to_path(u64 config) 160f6bdafefSJason Baron { 1611ef2ed10SFrederic Weisbecker struct tracepoint_path *path = NULL; 162f6bdafefSJason Baron DIR *sys_dir, *evt_dir; 163f6bdafefSJason Baron struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 164f6bdafefSJason Baron char id_buf[4]; 165725b1368SEric Dumazet int fd; 166f6bdafefSJason Baron u64 id; 167f6bdafefSJason Baron char evt_path[MAXPATHLEN]; 168725b1368SEric Dumazet char dir_path[MAXPATHLEN]; 169f6bdafefSJason Baron 170549104f2SClark Williams if (debugfs_valid_mountpoint(debugfs_path)) 1711ef2ed10SFrederic Weisbecker return NULL; 172f6bdafefSJason Baron 1735beeded1SJason Baron sys_dir = opendir(debugfs_path); 174f6bdafefSJason Baron if (!sys_dir) 175725b1368SEric Dumazet return NULL; 176f6bdafefSJason Baron 1776b58e7f1SUlrich Drepper for_each_subsystem(sys_dir, sys_dirent, sys_next) { 178725b1368SEric Dumazet 179725b1368SEric Dumazet snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 180725b1368SEric Dumazet sys_dirent.d_name); 181725b1368SEric Dumazet evt_dir = opendir(dir_path); 182725b1368SEric Dumazet if (!evt_dir) 1836b58e7f1SUlrich Drepper continue; 184725b1368SEric Dumazet 1856b58e7f1SUlrich Drepper for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 186725b1368SEric Dumazet 187725b1368SEric Dumazet snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, 188f6bdafefSJason Baron evt_dirent.d_name); 189725b1368SEric Dumazet fd = open(evt_path, O_RDONLY); 190f6bdafefSJason Baron if (fd < 0) 191f6bdafefSJason Baron continue; 192f6bdafefSJason Baron if (read(fd, id_buf, sizeof(id_buf)) < 0) { 193f6bdafefSJason Baron close(fd); 194f6bdafefSJason Baron continue; 195f6bdafefSJason Baron } 196f6bdafefSJason Baron close(fd); 197f6bdafefSJason Baron id = atoll(id_buf); 198f6bdafefSJason Baron if (id == config) { 199f6bdafefSJason Baron closedir(evt_dir); 200f6bdafefSJason Baron closedir(sys_dir); 20159b4caebSJulia Lawall path = zalloc(sizeof(*path)); 2021ef2ed10SFrederic Weisbecker path->system = malloc(MAX_EVENT_LENGTH); 2031ef2ed10SFrederic Weisbecker if (!path->system) { 2041ef2ed10SFrederic Weisbecker free(path); 2051ef2ed10SFrederic Weisbecker return NULL; 2061ef2ed10SFrederic Weisbecker } 2071ef2ed10SFrederic Weisbecker path->name = malloc(MAX_EVENT_LENGTH); 2081ef2ed10SFrederic Weisbecker if (!path->name) { 2091ef2ed10SFrederic Weisbecker free(path->system); 2101ef2ed10SFrederic Weisbecker free(path); 2111ef2ed10SFrederic Weisbecker return NULL; 2121ef2ed10SFrederic Weisbecker } 2131ef2ed10SFrederic Weisbecker strncpy(path->system, sys_dirent.d_name, 2141ef2ed10SFrederic Weisbecker MAX_EVENT_LENGTH); 2151ef2ed10SFrederic Weisbecker strncpy(path->name, evt_dirent.d_name, 2161ef2ed10SFrederic Weisbecker MAX_EVENT_LENGTH); 2171ef2ed10SFrederic Weisbecker return path; 218f6bdafefSJason Baron } 219f6bdafefSJason Baron } 220f6bdafefSJason Baron closedir(evt_dir); 221f6bdafefSJason Baron } 222f6bdafefSJason Baron 223f6bdafefSJason Baron closedir(sys_dir); 2241ef2ed10SFrederic Weisbecker return NULL; 2251ef2ed10SFrederic Weisbecker } 2261ef2ed10SFrederic Weisbecker 2271ef2ed10SFrederic Weisbecker #define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1) 2281ef2ed10SFrederic Weisbecker static const char *tracepoint_id_to_name(u64 config) 2291ef2ed10SFrederic Weisbecker { 2301ef2ed10SFrederic Weisbecker static char buf[TP_PATH_LEN]; 2311ef2ed10SFrederic Weisbecker struct tracepoint_path *path; 2321ef2ed10SFrederic Weisbecker 2331ef2ed10SFrederic Weisbecker path = tracepoint_id_to_path(config); 2341ef2ed10SFrederic Weisbecker if (path) { 2351ef2ed10SFrederic Weisbecker snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name); 2361ef2ed10SFrederic Weisbecker free(path->name); 2371ef2ed10SFrederic Weisbecker free(path->system); 2381ef2ed10SFrederic Weisbecker free(path); 2391ef2ed10SFrederic Weisbecker } else 2401ef2ed10SFrederic Weisbecker snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown"); 2411ef2ed10SFrederic Weisbecker 2421ef2ed10SFrederic Weisbecker return buf; 243f6bdafefSJason Baron } 244f6bdafefSJason Baron 24506813f6cSJaswinder Singh Rajput static int is_cache_op_valid(u8 cache_type, u8 cache_op) 24606813f6cSJaswinder Singh Rajput { 24706813f6cSJaswinder Singh Rajput if (hw_cache_stat[cache_type] & COP(cache_op)) 24806813f6cSJaswinder Singh Rajput return 1; /* valid */ 24906813f6cSJaswinder Singh Rajput else 25006813f6cSJaswinder Singh Rajput return 0; /* invalid */ 25106813f6cSJaswinder Singh Rajput } 25206813f6cSJaswinder Singh Rajput 253e5c59547SJaswinder Singh Rajput static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result) 254e5c59547SJaswinder Singh Rajput { 255e5c59547SJaswinder Singh Rajput static char name[50]; 256e5c59547SJaswinder Singh Rajput 257e5c59547SJaswinder Singh Rajput if (cache_result) { 258e5c59547SJaswinder Singh Rajput sprintf(name, "%s-%s-%s", hw_cache[cache_type][0], 259e5c59547SJaswinder Singh Rajput hw_cache_op[cache_op][0], 260e5c59547SJaswinder Singh Rajput hw_cache_result[cache_result][0]); 261e5c59547SJaswinder Singh Rajput } else { 262e5c59547SJaswinder Singh Rajput sprintf(name, "%s-%s", hw_cache[cache_type][0], 263e5c59547SJaswinder Singh Rajput hw_cache_op[cache_op][1]); 264e5c59547SJaswinder Singh Rajput } 265e5c59547SJaswinder Singh Rajput 266e5c59547SJaswinder Singh Rajput return name; 267e5c59547SJaswinder Singh Rajput } 268e5c59547SJaswinder Singh Rajput 26969aad6f1SArnaldo Carvalho de Melo const char *event_name(struct perf_evsel *evsel) 27086470930SIngo Molnar { 27169aad6f1SArnaldo Carvalho de Melo u64 config = evsel->attr.config; 27269aad6f1SArnaldo Carvalho de Melo int type = evsel->attr.type; 2738f18aec5SPeter Zijlstra 2748f18aec5SPeter Zijlstra return __event_name(type, config); 2758f18aec5SPeter Zijlstra } 2768f18aec5SPeter Zijlstra 27783a0944fSIngo Molnar const char *__event_name(int type, u64 config) 2788f18aec5SPeter Zijlstra { 27986470930SIngo Molnar static char buf[32]; 28086470930SIngo Molnar 2818f18aec5SPeter Zijlstra if (type == PERF_TYPE_RAW) { 28286470930SIngo Molnar sprintf(buf, "raw 0x%llx", config); 28386470930SIngo Molnar return buf; 28486470930SIngo Molnar } 28586470930SIngo Molnar 28686470930SIngo Molnar switch (type) { 28786470930SIngo Molnar case PERF_TYPE_HARDWARE: 288f4dbfa8fSPeter Zijlstra if (config < PERF_COUNT_HW_MAX) 28986470930SIngo Molnar return hw_event_names[config]; 29086470930SIngo Molnar return "unknown-hardware"; 29186470930SIngo Molnar 29286470930SIngo Molnar case PERF_TYPE_HW_CACHE: { 2939cffa8d5SPaul Mackerras u8 cache_type, cache_op, cache_result; 29486470930SIngo Molnar 29586470930SIngo Molnar cache_type = (config >> 0) & 0xff; 29686470930SIngo Molnar if (cache_type > PERF_COUNT_HW_CACHE_MAX) 29786470930SIngo Molnar return "unknown-ext-hardware-cache-type"; 29886470930SIngo Molnar 29986470930SIngo Molnar cache_op = (config >> 8) & 0xff; 30086470930SIngo Molnar if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX) 30186470930SIngo Molnar return "unknown-ext-hardware-cache-op"; 30286470930SIngo Molnar 30386470930SIngo Molnar cache_result = (config >> 16) & 0xff; 30486470930SIngo Molnar if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX) 30586470930SIngo Molnar return "unknown-ext-hardware-cache-result"; 30686470930SIngo Molnar 30706813f6cSJaswinder Singh Rajput if (!is_cache_op_valid(cache_type, cache_op)) 30806813f6cSJaswinder Singh Rajput return "invalid-cache"; 30986470930SIngo Molnar 310e5c59547SJaswinder Singh Rajput return event_cache_name(cache_type, cache_op, cache_result); 31186470930SIngo Molnar } 31286470930SIngo Molnar 31386470930SIngo Molnar case PERF_TYPE_SOFTWARE: 314f4dbfa8fSPeter Zijlstra if (config < PERF_COUNT_SW_MAX) 31586470930SIngo Molnar return sw_event_names[config]; 31686470930SIngo Molnar return "unknown-software"; 31786470930SIngo Molnar 318f6bdafefSJason Baron case PERF_TYPE_TRACEPOINT: 319f6bdafefSJason Baron return tracepoint_id_to_name(config); 320f6bdafefSJason Baron 32186470930SIngo Molnar default: 32286470930SIngo Molnar break; 32386470930SIngo Molnar } 32486470930SIngo Molnar 32586470930SIngo Molnar return "unknown"; 32686470930SIngo Molnar } 32786470930SIngo Molnar 32883a0944fSIngo Molnar static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size) 32986470930SIngo Molnar { 33086470930SIngo Molnar int i, j; 33161c45981SPaul Mackerras int n, longest = -1; 33286470930SIngo Molnar 33386470930SIngo Molnar for (i = 0; i < size; i++) { 33461c45981SPaul Mackerras for (j = 0; j < MAX_ALIASES && names[i][j]; j++) { 33561c45981SPaul Mackerras n = strlen(names[i][j]); 33661c45981SPaul Mackerras if (n > longest && !strncasecmp(*str, names[i][j], n)) 33761c45981SPaul Mackerras longest = n; 33861c45981SPaul Mackerras } 33961c45981SPaul Mackerras if (longest > 0) { 34061c45981SPaul Mackerras *str += longest; 34186470930SIngo Molnar return i; 34286470930SIngo Molnar } 34386470930SIngo Molnar } 34486470930SIngo Molnar 3458953645fSIngo Molnar return -1; 34686470930SIngo Molnar } 34786470930SIngo Molnar 348bcd3279fSFrederic Weisbecker static enum event_result 349cdd6c482SIngo Molnar parse_generic_hw_event(const char **str, struct perf_event_attr *attr) 35086470930SIngo Molnar { 35161c45981SPaul Mackerras const char *s = *str; 35261c45981SPaul Mackerras int cache_type = -1, cache_op = -1, cache_result = -1; 35386470930SIngo Molnar 35461c45981SPaul Mackerras cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX); 35586470930SIngo Molnar /* 35686470930SIngo Molnar * No fallback - if we cannot get a clear cache type 35786470930SIngo Molnar * then bail out: 35886470930SIngo Molnar */ 35986470930SIngo Molnar if (cache_type == -1) 360bcd3279fSFrederic Weisbecker return EVT_FAILED; 36186470930SIngo Molnar 36261c45981SPaul Mackerras while ((cache_op == -1 || cache_result == -1) && *s == '-') { 36361c45981SPaul Mackerras ++s; 36461c45981SPaul Mackerras 36561c45981SPaul Mackerras if (cache_op == -1) { 36661c45981SPaul Mackerras cache_op = parse_aliases(&s, hw_cache_op, 36761c45981SPaul Mackerras PERF_COUNT_HW_CACHE_OP_MAX); 36861c45981SPaul Mackerras if (cache_op >= 0) { 36961c45981SPaul Mackerras if (!is_cache_op_valid(cache_type, cache_op)) 37061c45981SPaul Mackerras return 0; 37161c45981SPaul Mackerras continue; 37261c45981SPaul Mackerras } 37361c45981SPaul Mackerras } 37461c45981SPaul Mackerras 37561c45981SPaul Mackerras if (cache_result == -1) { 37661c45981SPaul Mackerras cache_result = parse_aliases(&s, hw_cache_result, 37761c45981SPaul Mackerras PERF_COUNT_HW_CACHE_RESULT_MAX); 37861c45981SPaul Mackerras if (cache_result >= 0) 37961c45981SPaul Mackerras continue; 38061c45981SPaul Mackerras } 38161c45981SPaul Mackerras 38261c45981SPaul Mackerras /* 38361c45981SPaul Mackerras * Can't parse this as a cache op or result, so back up 38461c45981SPaul Mackerras * to the '-'. 38561c45981SPaul Mackerras */ 38661c45981SPaul Mackerras --s; 38761c45981SPaul Mackerras break; 38861c45981SPaul Mackerras } 38961c45981SPaul Mackerras 39086470930SIngo Molnar /* 39186470930SIngo Molnar * Fall back to reads: 39286470930SIngo Molnar */ 3938953645fSIngo Molnar if (cache_op == -1) 3948953645fSIngo Molnar cache_op = PERF_COUNT_HW_CACHE_OP_READ; 39586470930SIngo Molnar 39686470930SIngo Molnar /* 39786470930SIngo Molnar * Fall back to accesses: 39886470930SIngo Molnar */ 39986470930SIngo Molnar if (cache_result == -1) 40086470930SIngo Molnar cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS; 40186470930SIngo Molnar 40286470930SIngo Molnar attr->config = cache_type | (cache_op << 8) | (cache_result << 16); 40386470930SIngo Molnar attr->type = PERF_TYPE_HW_CACHE; 40486470930SIngo Molnar 40561c45981SPaul Mackerras *str = s; 406bcd3279fSFrederic Weisbecker return EVT_HANDLED; 40786470930SIngo Molnar } 40886470930SIngo Molnar 409bcd3279fSFrederic Weisbecker static enum event_result 410bcd3279fSFrederic Weisbecker parse_single_tracepoint_event(char *sys_name, 411bcd3279fSFrederic Weisbecker const char *evt_name, 412bcd3279fSFrederic Weisbecker unsigned int evt_length, 413cdd6c482SIngo Molnar struct perf_event_attr *attr, 414bcd3279fSFrederic Weisbecker const char **strp) 415bcd3279fSFrederic Weisbecker { 416bcd3279fSFrederic Weisbecker char evt_path[MAXPATHLEN]; 417bcd3279fSFrederic Weisbecker char id_buf[4]; 418bcd3279fSFrederic Weisbecker u64 id; 419bcd3279fSFrederic Weisbecker int fd; 420bcd3279fSFrederic Weisbecker 421bcd3279fSFrederic Weisbecker snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 422bcd3279fSFrederic Weisbecker sys_name, evt_name); 423bcd3279fSFrederic Weisbecker 424bcd3279fSFrederic Weisbecker fd = open(evt_path, O_RDONLY); 425bcd3279fSFrederic Weisbecker if (fd < 0) 426bcd3279fSFrederic Weisbecker return EVT_FAILED; 427bcd3279fSFrederic Weisbecker 428bcd3279fSFrederic Weisbecker if (read(fd, id_buf, sizeof(id_buf)) < 0) { 429bcd3279fSFrederic Weisbecker close(fd); 430bcd3279fSFrederic Weisbecker return EVT_FAILED; 431bcd3279fSFrederic Weisbecker } 432bcd3279fSFrederic Weisbecker 433bcd3279fSFrederic Weisbecker close(fd); 434bcd3279fSFrederic Weisbecker id = atoll(id_buf); 435bcd3279fSFrederic Weisbecker attr->config = id; 436bcd3279fSFrederic Weisbecker attr->type = PERF_TYPE_TRACEPOINT; 4374c635a4eSCorey Ashford *strp += strlen(sys_name) + evt_length + 1; /* + 1 for the ':' */ 438bcd3279fSFrederic Weisbecker 4395710fcadSStephane Eranian attr->sample_type |= PERF_SAMPLE_RAW; 4405710fcadSStephane Eranian attr->sample_type |= PERF_SAMPLE_TIME; 4415710fcadSStephane Eranian attr->sample_type |= PERF_SAMPLE_CPU; 4425710fcadSStephane Eranian 4435710fcadSStephane Eranian attr->sample_period = 1; 4445710fcadSStephane Eranian 4455710fcadSStephane Eranian 446bcd3279fSFrederic Weisbecker return EVT_HANDLED; 447bcd3279fSFrederic Weisbecker } 448bcd3279fSFrederic Weisbecker 449bcd3279fSFrederic Weisbecker /* sys + ':' + event + ':' + flags*/ 450bcd3279fSFrederic Weisbecker #define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128) 451bcd3279fSFrederic Weisbecker static enum event_result 452fb1d2edfSMasami Hiramatsu parse_multiple_tracepoint_event(char *sys_name, const char *evt_exp, 453fb1d2edfSMasami Hiramatsu char *flags) 454bcd3279fSFrederic Weisbecker { 455bcd3279fSFrederic Weisbecker char evt_path[MAXPATHLEN]; 456bcd3279fSFrederic Weisbecker struct dirent *evt_ent; 457bcd3279fSFrederic Weisbecker DIR *evt_dir; 458bcd3279fSFrederic Weisbecker 459bcd3279fSFrederic Weisbecker snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name); 460bcd3279fSFrederic Weisbecker evt_dir = opendir(evt_path); 461bcd3279fSFrederic Weisbecker 462bcd3279fSFrederic Weisbecker if (!evt_dir) { 463bcd3279fSFrederic Weisbecker perror("Can't open event dir"); 464bcd3279fSFrederic Weisbecker return EVT_FAILED; 465bcd3279fSFrederic Weisbecker } 466bcd3279fSFrederic Weisbecker 467bcd3279fSFrederic Weisbecker while ((evt_ent = readdir(evt_dir))) { 468bcd3279fSFrederic Weisbecker char event_opt[MAX_EVOPT_LEN + 1]; 469bcd3279fSFrederic Weisbecker int len; 470bcd3279fSFrederic Weisbecker 471bcd3279fSFrederic Weisbecker if (!strcmp(evt_ent->d_name, ".") 472bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "..") 473bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "enable") 474bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "filter")) 475bcd3279fSFrederic Weisbecker continue; 476bcd3279fSFrederic Weisbecker 477fb1d2edfSMasami Hiramatsu if (!strglobmatch(evt_ent->d_name, evt_exp)) 478fb1d2edfSMasami Hiramatsu continue; 479fb1d2edfSMasami Hiramatsu 480180570fdSUlrich Drepper len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s%s%s", sys_name, 481180570fdSUlrich Drepper evt_ent->d_name, flags ? ":" : "", 482180570fdSUlrich Drepper flags ?: ""); 483bcd3279fSFrederic Weisbecker if (len < 0) 484bcd3279fSFrederic Weisbecker return EVT_FAILED; 485bcd3279fSFrederic Weisbecker 486bcd3279fSFrederic Weisbecker if (parse_events(NULL, event_opt, 0)) 487bcd3279fSFrederic Weisbecker return EVT_FAILED; 488bcd3279fSFrederic Weisbecker } 489bcd3279fSFrederic Weisbecker 490bcd3279fSFrederic Weisbecker return EVT_HANDLED_ALL; 491bcd3279fSFrederic Weisbecker } 492bcd3279fSFrederic Weisbecker 493bcd3279fSFrederic Weisbecker 494bcd3279fSFrederic Weisbecker static enum event_result parse_tracepoint_event(const char **strp, 495cdd6c482SIngo Molnar struct perf_event_attr *attr) 496f6bdafefSJason Baron { 497f6bdafefSJason Baron const char *evt_name; 4984c635a4eSCorey Ashford char *flags = NULL, *comma_loc; 499f6bdafefSJason Baron char sys_name[MAX_EVENT_LENGTH]; 500f6bdafefSJason Baron unsigned int sys_length, evt_length; 501f6bdafefSJason Baron 502549104f2SClark Williams if (debugfs_valid_mountpoint(debugfs_path)) 503f6bdafefSJason Baron return 0; 504f6bdafefSJason Baron 505f6bdafefSJason Baron evt_name = strchr(*strp, ':'); 506f6bdafefSJason Baron if (!evt_name) 507bcd3279fSFrederic Weisbecker return EVT_FAILED; 508f6bdafefSJason Baron 509f6bdafefSJason Baron sys_length = evt_name - *strp; 510f6bdafefSJason Baron if (sys_length >= MAX_EVENT_LENGTH) 511f6bdafefSJason Baron return 0; 512f6bdafefSJason Baron 513f6bdafefSJason Baron strncpy(sys_name, *strp, sys_length); 514f6bdafefSJason Baron sys_name[sys_length] = '\0'; 515f6bdafefSJason Baron evt_name = evt_name + 1; 5163a9f131fSFrederic Weisbecker 5174c635a4eSCorey Ashford comma_loc = strchr(evt_name, ','); 5184c635a4eSCorey Ashford if (comma_loc) { 5194c635a4eSCorey Ashford /* take the event name up to the comma */ 5204c635a4eSCorey Ashford evt_name = strndup(evt_name, comma_loc - evt_name); 5214c635a4eSCorey Ashford } 5223a9f131fSFrederic Weisbecker flags = strchr(evt_name, ':'); 5233a9f131fSFrederic Weisbecker if (flags) { 5241fc35b29SIngo Molnar /* split it out: */ 5251fc35b29SIngo Molnar evt_name = strndup(evt_name, flags - evt_name); 5263a9f131fSFrederic Weisbecker flags++; 5273a9f131fSFrederic Weisbecker } 5283a9f131fSFrederic Weisbecker 529f6bdafefSJason Baron evt_length = strlen(evt_name); 530f6bdafefSJason Baron if (evt_length >= MAX_EVENT_LENGTH) 531bcd3279fSFrederic Weisbecker return EVT_FAILED; 532fb1d2edfSMasami Hiramatsu if (strpbrk(evt_name, "*?")) { 5334c635a4eSCorey Ashford *strp += strlen(sys_name) + evt_length; 534fb1d2edfSMasami Hiramatsu return parse_multiple_tracepoint_event(sys_name, evt_name, 535fb1d2edfSMasami Hiramatsu flags); 536bcd3279fSFrederic Weisbecker } else 537bcd3279fSFrederic Weisbecker return parse_single_tracepoint_event(sys_name, evt_name, 538bdef3b02SFrederic Weisbecker evt_length, attr, strp); 539f6bdafefSJason Baron } 540f6bdafefSJason Baron 5411b290d67SFrederic Weisbecker static enum event_result 5421b290d67SFrederic Weisbecker parse_breakpoint_type(const char *type, const char **strp, 5431b290d67SFrederic Weisbecker struct perf_event_attr *attr) 5441b290d67SFrederic Weisbecker { 5451b290d67SFrederic Weisbecker int i; 5461b290d67SFrederic Weisbecker 5471b290d67SFrederic Weisbecker for (i = 0; i < 3; i++) { 5481b290d67SFrederic Weisbecker if (!type[i]) 5491b290d67SFrederic Weisbecker break; 5501b290d67SFrederic Weisbecker 5511b290d67SFrederic Weisbecker switch (type[i]) { 5521b290d67SFrederic Weisbecker case 'r': 5531b290d67SFrederic Weisbecker attr->bp_type |= HW_BREAKPOINT_R; 5541b290d67SFrederic Weisbecker break; 5551b290d67SFrederic Weisbecker case 'w': 5561b290d67SFrederic Weisbecker attr->bp_type |= HW_BREAKPOINT_W; 5571b290d67SFrederic Weisbecker break; 5581b290d67SFrederic Weisbecker case 'x': 5591b290d67SFrederic Weisbecker attr->bp_type |= HW_BREAKPOINT_X; 5601b290d67SFrederic Weisbecker break; 5611b290d67SFrederic Weisbecker default: 5621b290d67SFrederic Weisbecker return EVT_FAILED; 5631b290d67SFrederic Weisbecker } 5641b290d67SFrederic Weisbecker } 5651b290d67SFrederic Weisbecker if (!attr->bp_type) /* Default */ 5661b290d67SFrederic Weisbecker attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; 5671b290d67SFrederic Weisbecker 5681b290d67SFrederic Weisbecker *strp = type + i; 5691b290d67SFrederic Weisbecker 5701b290d67SFrederic Weisbecker return EVT_HANDLED; 5711b290d67SFrederic Weisbecker } 5721b290d67SFrederic Weisbecker 5731b290d67SFrederic Weisbecker static enum event_result 5741b290d67SFrederic Weisbecker parse_breakpoint_event(const char **strp, struct perf_event_attr *attr) 5751b290d67SFrederic Weisbecker { 5761b290d67SFrederic Weisbecker const char *target; 5771b290d67SFrederic Weisbecker const char *type; 5781b290d67SFrederic Weisbecker char *endaddr; 5791b290d67SFrederic Weisbecker u64 addr; 5801b290d67SFrederic Weisbecker enum event_result err; 5811b290d67SFrederic Weisbecker 5821b290d67SFrederic Weisbecker target = strchr(*strp, ':'); 5831b290d67SFrederic Weisbecker if (!target) 5841b290d67SFrederic Weisbecker return EVT_FAILED; 5851b290d67SFrederic Weisbecker 5861b290d67SFrederic Weisbecker if (strncmp(*strp, "mem", target - *strp) != 0) 5871b290d67SFrederic Weisbecker return EVT_FAILED; 5881b290d67SFrederic Weisbecker 5891b290d67SFrederic Weisbecker target++; 5901b290d67SFrederic Weisbecker 5911b290d67SFrederic Weisbecker addr = strtoull(target, &endaddr, 0); 5921b290d67SFrederic Weisbecker if (target == endaddr) 5931b290d67SFrederic Weisbecker return EVT_FAILED; 5941b290d67SFrederic Weisbecker 5951b290d67SFrederic Weisbecker attr->bp_addr = addr; 5961b290d67SFrederic Weisbecker *strp = endaddr; 5971b290d67SFrederic Weisbecker 5981b290d67SFrederic Weisbecker type = strchr(target, ':'); 5991b290d67SFrederic Weisbecker 6001b290d67SFrederic Weisbecker /* If no type is defined, just rw as default */ 6011b290d67SFrederic Weisbecker if (!type) { 6021b290d67SFrederic Weisbecker attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; 6031b290d67SFrederic Weisbecker } else { 6041b290d67SFrederic Weisbecker err = parse_breakpoint_type(++type, strp, attr); 6051b290d67SFrederic Weisbecker if (err == EVT_FAILED) 6061b290d67SFrederic Weisbecker return EVT_FAILED; 6071b290d67SFrederic Weisbecker } 6081b290d67SFrederic Weisbecker 609aa59a485SFrederic Weisbecker /* 610aa59a485SFrederic Weisbecker * We should find a nice way to override the access length 611aa59a485SFrederic Weisbecker * Provide some defaults for now 612aa59a485SFrederic Weisbecker */ 613aa59a485SFrederic Weisbecker if (attr->bp_type == HW_BREAKPOINT_X) 614aa59a485SFrederic Weisbecker attr->bp_len = sizeof(long); 615aa59a485SFrederic Weisbecker else 6161b290d67SFrederic Weisbecker attr->bp_len = HW_BREAKPOINT_LEN_4; 617aa59a485SFrederic Weisbecker 6181b290d67SFrederic Weisbecker attr->type = PERF_TYPE_BREAKPOINT; 6191b290d67SFrederic Weisbecker 6201b290d67SFrederic Weisbecker return EVT_HANDLED; 6211b290d67SFrederic Weisbecker } 6221b290d67SFrederic Weisbecker 62374d5b588SJaswinder Singh Rajput static int check_events(const char *str, unsigned int i) 62474d5b588SJaswinder Singh Rajput { 62561c45981SPaul Mackerras int n; 62674d5b588SJaswinder Singh Rajput 62761c45981SPaul Mackerras n = strlen(event_symbols[i].symbol); 62861c45981SPaul Mackerras if (!strncmp(str, event_symbols[i].symbol, n)) 62961c45981SPaul Mackerras return n; 63061c45981SPaul Mackerras 63161c45981SPaul Mackerras n = strlen(event_symbols[i].alias); 63261c45981SPaul Mackerras if (n) 63361c45981SPaul Mackerras if (!strncmp(str, event_symbols[i].alias, n)) 63461c45981SPaul Mackerras return n; 63561c45981SPaul Mackerras return 0; 63661c45981SPaul Mackerras } 63761c45981SPaul Mackerras 638bcd3279fSFrederic Weisbecker static enum event_result 639cdd6c482SIngo Molnar parse_symbolic_event(const char **strp, struct perf_event_attr *attr) 64061c45981SPaul Mackerras { 64161c45981SPaul Mackerras const char *str = *strp; 64261c45981SPaul Mackerras unsigned int i; 64361c45981SPaul Mackerras int n; 64461c45981SPaul Mackerras 64561c45981SPaul Mackerras for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { 64661c45981SPaul Mackerras n = check_events(str, i); 64761c45981SPaul Mackerras if (n > 0) { 64861c45981SPaul Mackerras attr->type = event_symbols[i].type; 64961c45981SPaul Mackerras attr->config = event_symbols[i].config; 65061c45981SPaul Mackerras *strp = str + n; 651bcd3279fSFrederic Weisbecker return EVT_HANDLED; 65261c45981SPaul Mackerras } 65361c45981SPaul Mackerras } 654bcd3279fSFrederic Weisbecker return EVT_FAILED; 65561c45981SPaul Mackerras } 65661c45981SPaul Mackerras 657bcd3279fSFrederic Weisbecker static enum event_result 658cdd6c482SIngo Molnar parse_raw_event(const char **strp, struct perf_event_attr *attr) 65961c45981SPaul Mackerras { 66061c45981SPaul Mackerras const char *str = *strp; 66161c45981SPaul Mackerras u64 config; 66261c45981SPaul Mackerras int n; 66361c45981SPaul Mackerras 66461c45981SPaul Mackerras if (*str != 'r') 665bcd3279fSFrederic Weisbecker return EVT_FAILED; 66661c45981SPaul Mackerras n = hex2u64(str + 1, &config); 66761c45981SPaul Mackerras if (n > 0) { 66861c45981SPaul Mackerras *strp = str + n + 1; 66961c45981SPaul Mackerras attr->type = PERF_TYPE_RAW; 67061c45981SPaul Mackerras attr->config = config; 671bcd3279fSFrederic Weisbecker return EVT_HANDLED; 67261c45981SPaul Mackerras } 673bcd3279fSFrederic Weisbecker return EVT_FAILED; 67461c45981SPaul Mackerras } 67561c45981SPaul Mackerras 676bcd3279fSFrederic Weisbecker static enum event_result 677cdd6c482SIngo Molnar parse_numeric_event(const char **strp, struct perf_event_attr *attr) 67861c45981SPaul Mackerras { 67961c45981SPaul Mackerras const char *str = *strp; 68061c45981SPaul Mackerras char *endp; 68161c45981SPaul Mackerras unsigned long type; 68261c45981SPaul Mackerras u64 config; 68361c45981SPaul Mackerras 68461c45981SPaul Mackerras type = strtoul(str, &endp, 0); 68561c45981SPaul Mackerras if (endp > str && type < PERF_TYPE_MAX && *endp == ':') { 68661c45981SPaul Mackerras str = endp + 1; 68761c45981SPaul Mackerras config = strtoul(str, &endp, 0); 68861c45981SPaul Mackerras if (endp > str) { 68961c45981SPaul Mackerras attr->type = type; 69061c45981SPaul Mackerras attr->config = config; 69161c45981SPaul Mackerras *strp = endp; 692bcd3279fSFrederic Weisbecker return EVT_HANDLED; 69361c45981SPaul Mackerras } 69461c45981SPaul Mackerras } 695bcd3279fSFrederic Weisbecker return EVT_FAILED; 69661c45981SPaul Mackerras } 69761c45981SPaul Mackerras 698bcd3279fSFrederic Weisbecker static enum event_result 699cdd6c482SIngo Molnar parse_event_modifier(const char **strp, struct perf_event_attr *attr) 70061c45981SPaul Mackerras { 70161c45981SPaul Mackerras const char *str = *strp; 702ab608344SPeter Zijlstra int exclude = 0; 703ab608344SPeter Zijlstra int eu = 0, ek = 0, eh = 0, precise = 0; 70461c45981SPaul Mackerras 70561c45981SPaul Mackerras if (*str++ != ':') 70661c45981SPaul Mackerras return 0; 70761c45981SPaul Mackerras while (*str) { 708ab608344SPeter Zijlstra if (*str == 'u') { 709ab608344SPeter Zijlstra if (!exclude) 710ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 71161c45981SPaul Mackerras eu = 0; 712ab608344SPeter Zijlstra } else if (*str == 'k') { 713ab608344SPeter Zijlstra if (!exclude) 714ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 71561c45981SPaul Mackerras ek = 0; 716ab608344SPeter Zijlstra } else if (*str == 'h') { 717ab608344SPeter Zijlstra if (!exclude) 718ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 71961c45981SPaul Mackerras eh = 0; 720ab608344SPeter Zijlstra } else if (*str == 'p') { 721ab608344SPeter Zijlstra precise++; 722ab608344SPeter Zijlstra } else 72361c45981SPaul Mackerras break; 724ab608344SPeter Zijlstra 72561c45981SPaul Mackerras ++str; 72661c45981SPaul Mackerras } 72761c45981SPaul Mackerras if (str >= *strp + 2) { 72861c45981SPaul Mackerras *strp = str; 72961c45981SPaul Mackerras attr->exclude_user = eu; 73061c45981SPaul Mackerras attr->exclude_kernel = ek; 73161c45981SPaul Mackerras attr->exclude_hv = eh; 732ab608344SPeter Zijlstra attr->precise_ip = precise; 73361c45981SPaul Mackerras return 1; 73461c45981SPaul Mackerras } 73574d5b588SJaswinder Singh Rajput return 0; 73674d5b588SJaswinder Singh Rajput } 73774d5b588SJaswinder Singh Rajput 73886470930SIngo Molnar /* 73986470930SIngo Molnar * Each event can have multiple symbolic names. 74086470930SIngo Molnar * Symbolic names are (almost) exactly matched. 74186470930SIngo Molnar */ 742bcd3279fSFrederic Weisbecker static enum event_result 743cdd6c482SIngo Molnar parse_event_symbols(const char **str, struct perf_event_attr *attr) 74486470930SIngo Molnar { 745bcd3279fSFrederic Weisbecker enum event_result ret; 74686470930SIngo Molnar 747bcd3279fSFrederic Weisbecker ret = parse_tracepoint_event(str, attr); 748bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 749bcd3279fSFrederic Weisbecker goto modifier; 750bcd3279fSFrederic Weisbecker 751bcd3279fSFrederic Weisbecker ret = parse_raw_event(str, attr); 752bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 753bcd3279fSFrederic Weisbecker goto modifier; 754bcd3279fSFrederic Weisbecker 755bcd3279fSFrederic Weisbecker ret = parse_numeric_event(str, attr); 756bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 757bcd3279fSFrederic Weisbecker goto modifier; 758bcd3279fSFrederic Weisbecker 759bcd3279fSFrederic Weisbecker ret = parse_symbolic_event(str, attr); 760bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 761bcd3279fSFrederic Weisbecker goto modifier; 762bcd3279fSFrederic Weisbecker 763bcd3279fSFrederic Weisbecker ret = parse_generic_hw_event(str, attr); 764bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 765bcd3279fSFrederic Weisbecker goto modifier; 766bcd3279fSFrederic Weisbecker 7671b290d67SFrederic Weisbecker ret = parse_breakpoint_event(str, attr); 7681b290d67SFrederic Weisbecker if (ret != EVT_FAILED) 7691b290d67SFrederic Weisbecker goto modifier; 7701b290d67SFrederic Weisbecker 77185df6f68SMarti Raudsepp fprintf(stderr, "invalid or unsupported event: '%s'\n", *str); 77285df6f68SMarti Raudsepp fprintf(stderr, "Run 'perf list' for a list of valid events\n"); 773bcd3279fSFrederic Weisbecker return EVT_FAILED; 774bcd3279fSFrederic Weisbecker 775bcd3279fSFrederic Weisbecker modifier: 77661c45981SPaul Mackerras parse_event_modifier(str, attr); 77786470930SIngo Molnar 778bcd3279fSFrederic Weisbecker return ret; 77986470930SIngo Molnar } 78086470930SIngo Molnar 781ae99fb2cSArnaldo Carvalho de Melo static int store_event_type(const char *orgname) 7828755a8f2SArjan van de Ven { 7838755a8f2SArjan van de Ven char filename[PATH_MAX], *c; 7848755a8f2SArjan van de Ven FILE *file; 785ae99fb2cSArnaldo Carvalho de Melo int id, n; 7868755a8f2SArjan van de Ven 78763c9e01eSAshwin Chaugule sprintf(filename, "%s/", debugfs_path); 78863c9e01eSAshwin Chaugule strncat(filename, orgname, strlen(orgname)); 78963c9e01eSAshwin Chaugule strcat(filename, "/id"); 79063c9e01eSAshwin Chaugule 7918755a8f2SArjan van de Ven c = strchr(filename, ':'); 7928755a8f2SArjan van de Ven if (c) 7938755a8f2SArjan van de Ven *c = '/'; 7948755a8f2SArjan van de Ven 7958755a8f2SArjan van de Ven file = fopen(filename, "r"); 7968755a8f2SArjan van de Ven if (!file) 797ae99fb2cSArnaldo Carvalho de Melo return 0; 798ae99fb2cSArnaldo Carvalho de Melo n = fscanf(file, "%i", &id); 7998755a8f2SArjan van de Ven fclose(file); 800ae99fb2cSArnaldo Carvalho de Melo if (n < 1) { 801ae99fb2cSArnaldo Carvalho de Melo pr_err("cannot store event ID\n"); 802ae99fb2cSArnaldo Carvalho de Melo return -EINVAL; 803ae99fb2cSArnaldo Carvalho de Melo } 804ae99fb2cSArnaldo Carvalho de Melo return perf_header__push_event(id, orgname); 8058755a8f2SArjan van de Ven } 8068755a8f2SArjan van de Ven 807f37a291cSIngo Molnar int parse_events(const struct option *opt __used, const char *str, int unset __used) 80886470930SIngo Molnar { 809cdd6c482SIngo Molnar struct perf_event_attr attr; 810bcd3279fSFrederic Weisbecker enum event_result ret; 81186470930SIngo Molnar 8128755a8f2SArjan van de Ven if (strchr(str, ':')) 813ae99fb2cSArnaldo Carvalho de Melo if (store_event_type(str) < 0) 814ae99fb2cSArnaldo Carvalho de Melo return -1; 8158755a8f2SArjan van de Ven 81661c45981SPaul Mackerras for (;;) { 81761c45981SPaul Mackerras memset(&attr, 0, sizeof(attr)); 818bcd3279fSFrederic Weisbecker ret = parse_event_symbols(&str, &attr); 819bcd3279fSFrederic Weisbecker if (ret == EVT_FAILED) 82061c45981SPaul Mackerras return -1; 82161c45981SPaul Mackerras 82261c45981SPaul Mackerras if (!(*str == 0 || *str == ',' || isspace(*str))) 82361c45981SPaul Mackerras return -1; 82486470930SIngo Molnar 825bcd3279fSFrederic Weisbecker if (ret != EVT_HANDLED_ALL) { 82669aad6f1SArnaldo Carvalho de Melo struct perf_evsel *evsel; 82769aad6f1SArnaldo Carvalho de Melo evsel = perf_evsel__new(attr.type, attr.config, 82869aad6f1SArnaldo Carvalho de Melo nr_counters); 82969aad6f1SArnaldo Carvalho de Melo if (evsel == NULL) 83069aad6f1SArnaldo Carvalho de Melo return -1; 83169aad6f1SArnaldo Carvalho de Melo list_add_tail(&evsel->node, &evsel_list); 83269aad6f1SArnaldo Carvalho de Melo ++nr_counters; 833bcd3279fSFrederic Weisbecker } 83486470930SIngo Molnar 83561c45981SPaul Mackerras if (*str == 0) 83661c45981SPaul Mackerras break; 83761c45981SPaul Mackerras if (*str == ',') 83861c45981SPaul Mackerras ++str; 83961c45981SPaul Mackerras while (isspace(*str)) 84061c45981SPaul Mackerras ++str; 84186470930SIngo Molnar } 84286470930SIngo Molnar 84386470930SIngo Molnar return 0; 84486470930SIngo Molnar } 84586470930SIngo Molnar 846c171b552SLi Zefan int parse_filter(const struct option *opt __used, const char *str, 847c171b552SLi Zefan int unset __used) 848c171b552SLi Zefan { 84969aad6f1SArnaldo Carvalho de Melo struct perf_evsel *last = NULL; 850c171b552SLi Zefan 85169aad6f1SArnaldo Carvalho de Melo if (!list_empty(&evsel_list)) 85269aad6f1SArnaldo Carvalho de Melo last = list_entry(evsel_list.prev, struct perf_evsel, node); 85369aad6f1SArnaldo Carvalho de Melo 85469aad6f1SArnaldo Carvalho de Melo if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) { 855c171b552SLi Zefan fprintf(stderr, 856c171b552SLi Zefan "-F option should follow a -e tracepoint option\n"); 857c171b552SLi Zefan return -1; 858c171b552SLi Zefan } 859c171b552SLi Zefan 86069aad6f1SArnaldo Carvalho de Melo last->filter = strdup(str); 86169aad6f1SArnaldo Carvalho de Melo if (last->filter == NULL) { 862c171b552SLi Zefan fprintf(stderr, "not enough memory to hold filter string\n"); 863c171b552SLi Zefan return -1; 864c171b552SLi Zefan } 865c171b552SLi Zefan 866c171b552SLi Zefan return 0; 867c171b552SLi Zefan } 868c171b552SLi Zefan 86986470930SIngo Molnar static const char * const event_type_descriptors[] = { 87086470930SIngo Molnar "Hardware event", 87186470930SIngo Molnar "Software event", 87286470930SIngo Molnar "Tracepoint event", 87386470930SIngo Molnar "Hardware cache event", 87441bdcb23SLiming Wang "Raw hardware event descriptor", 87541bdcb23SLiming Wang "Hardware breakpoint", 87686470930SIngo Molnar }; 87786470930SIngo Molnar 87886470930SIngo Molnar /* 879f6bdafefSJason Baron * Print the events from <debugfs_mount_point>/tracing/events 880f6bdafefSJason Baron */ 881f6bdafefSJason Baron 882f6bdafefSJason Baron static void print_tracepoint_events(void) 883f6bdafefSJason Baron { 884f6bdafefSJason Baron DIR *sys_dir, *evt_dir; 885f6bdafefSJason Baron struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 886f6bdafefSJason Baron char evt_path[MAXPATHLEN]; 887725b1368SEric Dumazet char dir_path[MAXPATHLEN]; 888f6bdafefSJason Baron 889549104f2SClark Williams if (debugfs_valid_mountpoint(debugfs_path)) 890f6bdafefSJason Baron return; 891f6bdafefSJason Baron 8925beeded1SJason Baron sys_dir = opendir(debugfs_path); 893f6bdafefSJason Baron if (!sys_dir) 894725b1368SEric Dumazet return; 895f6bdafefSJason Baron 8966b58e7f1SUlrich Drepper for_each_subsystem(sys_dir, sys_dirent, sys_next) { 897725b1368SEric Dumazet 898725b1368SEric Dumazet snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 899725b1368SEric Dumazet sys_dirent.d_name); 900725b1368SEric Dumazet evt_dir = opendir(dir_path); 901725b1368SEric Dumazet if (!evt_dir) 9026b58e7f1SUlrich Drepper continue; 903725b1368SEric Dumazet 9046b58e7f1SUlrich Drepper for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 905f6bdafefSJason Baron snprintf(evt_path, MAXPATHLEN, "%s:%s", 906f6bdafefSJason Baron sys_dirent.d_name, evt_dirent.d_name); 907689d3018SMarti Raudsepp printf(" %-42s [%s]\n", evt_path, 90841bdcb23SLiming Wang event_type_descriptors[PERF_TYPE_TRACEPOINT]); 909f6bdafefSJason Baron } 910f6bdafefSJason Baron closedir(evt_dir); 911f6bdafefSJason Baron } 912f6bdafefSJason Baron closedir(sys_dir); 913f6bdafefSJason Baron } 914f6bdafefSJason Baron 915f6bdafefSJason Baron /* 91686470930SIngo Molnar * Print the help text for the event symbols: 91786470930SIngo Molnar */ 91886470930SIngo Molnar void print_events(void) 91986470930SIngo Molnar { 92086470930SIngo Molnar struct event_symbol *syms = event_symbols; 92173c24cb8SJaswinder Singh Rajput unsigned int i, type, op, prev_type = -1; 92274d5b588SJaswinder Singh Rajput char name[40]; 92386470930SIngo Molnar 924689d3018SMarti Raudsepp printf("\n"); 925689d3018SMarti Raudsepp printf("List of pre-defined events (to be used in -e):\n"); 92686470930SIngo Molnar 92786470930SIngo Molnar for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 92841bdcb23SLiming Wang type = syms->type; 92986470930SIngo Molnar 93086470930SIngo Molnar if (type != prev_type) 931689d3018SMarti Raudsepp printf("\n"); 93286470930SIngo Molnar 93374d5b588SJaswinder Singh Rajput if (strlen(syms->alias)) 93474d5b588SJaswinder Singh Rajput sprintf(name, "%s OR %s", syms->symbol, syms->alias); 93574d5b588SJaswinder Singh Rajput else 93674d5b588SJaswinder Singh Rajput strcpy(name, syms->symbol); 937689d3018SMarti Raudsepp printf(" %-42s [%s]\n", name, 93886470930SIngo Molnar event_type_descriptors[type]); 93986470930SIngo Molnar 94086470930SIngo Molnar prev_type = type; 94186470930SIngo Molnar } 94286470930SIngo Molnar 943689d3018SMarti Raudsepp printf("\n"); 94473c24cb8SJaswinder Singh Rajput for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 94573c24cb8SJaswinder Singh Rajput for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 94673c24cb8SJaswinder Singh Rajput /* skip invalid cache type */ 94773c24cb8SJaswinder Singh Rajput if (!is_cache_op_valid(type, op)) 94873c24cb8SJaswinder Singh Rajput continue; 94973c24cb8SJaswinder Singh Rajput 95073c24cb8SJaswinder Singh Rajput for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { 951689d3018SMarti Raudsepp printf(" %-42s [%s]\n", 95273c24cb8SJaswinder Singh Rajput event_cache_name(type, op, i), 95341bdcb23SLiming Wang event_type_descriptors[PERF_TYPE_HW_CACHE]); 95473c24cb8SJaswinder Singh Rajput } 95573c24cb8SJaswinder Singh Rajput } 95673c24cb8SJaswinder Singh Rajput } 95773c24cb8SJaswinder Singh Rajput 958689d3018SMarti Raudsepp printf("\n"); 95941bdcb23SLiming Wang printf(" %-42s [%s]\n", 9601cf4a063SArnaldo Carvalho de Melo "rNNN (see 'perf list --help' on how to encode it)", 9611cf4a063SArnaldo Carvalho de Melo event_type_descriptors[PERF_TYPE_RAW]); 962689d3018SMarti Raudsepp printf("\n"); 96386470930SIngo Molnar 96441bdcb23SLiming Wang printf(" %-42s [%s]\n", 96541bdcb23SLiming Wang "mem:<addr>[:access]", 96641bdcb23SLiming Wang event_type_descriptors[PERF_TYPE_BREAKPOINT]); 9671b290d67SFrederic Weisbecker printf("\n"); 9681b290d67SFrederic Weisbecker 969f6bdafefSJason Baron print_tracepoint_events(); 970f6bdafefSJason Baron 97186470930SIngo Molnar exit(129); 97286470930SIngo Molnar } 97369aad6f1SArnaldo Carvalho de Melo 97469aad6f1SArnaldo Carvalho de Melo int perf_evsel_list__create_default(void) 97569aad6f1SArnaldo Carvalho de Melo { 97669aad6f1SArnaldo Carvalho de Melo struct perf_evsel *evsel = perf_evsel__new(PERF_TYPE_HARDWARE, 97769aad6f1SArnaldo Carvalho de Melo PERF_COUNT_HW_CPU_CYCLES, 0); 97869aad6f1SArnaldo Carvalho de Melo if (evsel == NULL) 97969aad6f1SArnaldo Carvalho de Melo return -ENOMEM; 98069aad6f1SArnaldo Carvalho de Melo 98169aad6f1SArnaldo Carvalho de Melo list_add(&evsel->node, &evsel_list); 98269aad6f1SArnaldo Carvalho de Melo ++nr_counters; 98369aad6f1SArnaldo Carvalho de Melo return 0; 98469aad6f1SArnaldo Carvalho de Melo } 985*70d544d0SArnaldo Carvalho de Melo 986*70d544d0SArnaldo Carvalho de Melo void perf_evsel_list__delete(void) 987*70d544d0SArnaldo Carvalho de Melo { 988*70d544d0SArnaldo Carvalho de Melo struct perf_evsel *pos, *n; 989*70d544d0SArnaldo Carvalho de Melo 990*70d544d0SArnaldo Carvalho de Melo list_for_each_entry_safe(pos, n, &evsel_list, node) { 991*70d544d0SArnaldo Carvalho de Melo list_del_init(&pos->node); 992*70d544d0SArnaldo Carvalho de Melo perf_evsel__delete(pos); 993*70d544d0SArnaldo Carvalho de Melo } 994*70d544d0SArnaldo Carvalho de Melo nr_counters = 0; 995*70d544d0SArnaldo Carvalho de Melo } 996