11b290d67SFrederic Weisbecker #include "../../../include/linux/hw_breakpoint.h" 286470930SIngo Molnar #include "util.h" 36b58e7f1SUlrich Drepper #include "../perf.h" 4361c99a6SArnaldo Carvalho de Melo #include "evlist.h" 569aad6f1SArnaldo Carvalho de Melo #include "evsel.h" 686470930SIngo Molnar #include "parse-options.h" 786470930SIngo Molnar #include "parse-events.h" 886470930SIngo Molnar #include "exec_cmd.h" 986470930SIngo Molnar #include "string.h" 105aab621bSArnaldo Carvalho de Melo #include "symbol.h" 115beeded1SJason Baron #include "cache.h" 128755a8f2SArjan van de Ven #include "header.h" 13549104f2SClark Williams #include "debugfs.h" 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" }, 35129c04cbSIngo Molnar { CHW(STALLED_CYCLES_FRONTEND), "stalled-cycles-frontend", "idle-cycles-frontend" }, 36129c04cbSIngo Molnar { CHW(STALLED_CYCLES_BACKEND), "stalled-cycles-backend", "idle-cycles-backend" }, 3774d5b588SJaswinder Singh Rajput { CHW(INSTRUCTIONS), "instructions", "" }, 3874d5b588SJaswinder Singh Rajput { CHW(CACHE_REFERENCES), "cache-references", "" }, 3974d5b588SJaswinder Singh Rajput { CHW(CACHE_MISSES), "cache-misses", "" }, 4074d5b588SJaswinder Singh Rajput { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" }, 4174d5b588SJaswinder Singh Rajput { CHW(BRANCH_MISSES), "branch-misses", "" }, 4274d5b588SJaswinder Singh Rajput { CHW(BUS_CYCLES), "bus-cycles", "" }, 4386470930SIngo Molnar 4474d5b588SJaswinder Singh Rajput { CSW(CPU_CLOCK), "cpu-clock", "" }, 4574d5b588SJaswinder Singh Rajput { CSW(TASK_CLOCK), "task-clock", "" }, 46c0c22dbfSJaswinder Singh Rajput { CSW(PAGE_FAULTS), "page-faults", "faults" }, 4774d5b588SJaswinder Singh Rajput { CSW(PAGE_FAULTS_MIN), "minor-faults", "" }, 4874d5b588SJaswinder Singh Rajput { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, 4974d5b588SJaswinder Singh Rajput { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, 5074d5b588SJaswinder Singh Rajput { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, 51f7d79860SAnton Blanchard { CSW(ALIGNMENT_FAULTS), "alignment-faults", "" }, 52f7d79860SAnton Blanchard { CSW(EMULATION_FAULTS), "emulation-faults", "" }, 5386470930SIngo Molnar }; 5486470930SIngo Molnar 55cdd6c482SIngo Molnar #define __PERF_EVENT_FIELD(config, name) \ 56cdd6c482SIngo Molnar ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT) 5786470930SIngo Molnar 58cdd6c482SIngo Molnar #define PERF_EVENT_RAW(config) __PERF_EVENT_FIELD(config, RAW) 59cdd6c482SIngo Molnar #define PERF_EVENT_CONFIG(config) __PERF_EVENT_FIELD(config, CONFIG) 60cdd6c482SIngo Molnar #define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE) 61cdd6c482SIngo Molnar #define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT) 6286470930SIngo Molnar 63d3d1e86dSIngo Molnar static const char *hw_event_names[PERF_COUNT_HW_MAX] = { 6486470930SIngo Molnar "cycles", 6586470930SIngo Molnar "instructions", 6686470930SIngo Molnar "cache-references", 6786470930SIngo Molnar "cache-misses", 6886470930SIngo Molnar "branches", 6986470930SIngo Molnar "branch-misses", 7086470930SIngo Molnar "bus-cycles", 71d3d1e86dSIngo Molnar "stalled-cycles-frontend", 72d3d1e86dSIngo Molnar "stalled-cycles-backend", 7386470930SIngo Molnar }; 7486470930SIngo Molnar 75d3d1e86dSIngo Molnar static const char *sw_event_names[PERF_COUNT_SW_MAX] = { 76749141d9SIngo Molnar "cpu-clock", 77749141d9SIngo Molnar "task-clock", 7886470930SIngo Molnar "page-faults", 7986470930SIngo Molnar "context-switches", 8086470930SIngo Molnar "CPU-migrations", 8186470930SIngo Molnar "minor-faults", 8286470930SIngo Molnar "major-faults", 83f7d79860SAnton Blanchard "alignment-faults", 84f7d79860SAnton Blanchard "emulation-faults", 8586470930SIngo Molnar }; 8686470930SIngo Molnar 8786470930SIngo Molnar #define MAX_ALIASES 8 8886470930SIngo Molnar 89*0111919dSJiri Olsa static const char *hw_cache[PERF_COUNT_HW_CACHE_MAX][MAX_ALIASES] = { 909590b7baSAnton Blanchard { "L1-dcache", "l1-d", "l1d", "L1-data", }, 919590b7baSAnton Blanchard { "L1-icache", "l1-i", "l1i", "L1-instruction", }, 92*0111919dSJiri Olsa { "LLC", "L2", }, 93e5c59547SJaswinder Singh Rajput { "dTLB", "d-tlb", "Data-TLB", }, 94e5c59547SJaswinder Singh Rajput { "iTLB", "i-tlb", "Instruction-TLB", }, 95e5c59547SJaswinder Singh Rajput { "branch", "branches", "bpu", "btb", "bpc", }, 96*0111919dSJiri Olsa { "node", }, 9786470930SIngo Molnar }; 9886470930SIngo Molnar 99*0111919dSJiri Olsa static const char *hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX][MAX_ALIASES] = { 100e5c59547SJaswinder Singh Rajput { "load", "loads", "read", }, 101e5c59547SJaswinder Singh Rajput { "store", "stores", "write", }, 102e5c59547SJaswinder Singh Rajput { "prefetch", "prefetches", "speculative-read", "speculative-load", }, 10386470930SIngo Molnar }; 10486470930SIngo Molnar 105*0111919dSJiri Olsa static const char *hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX] 106*0111919dSJiri Olsa [MAX_ALIASES] = { 107e5c59547SJaswinder Singh Rajput { "refs", "Reference", "ops", "access", }, 108e5c59547SJaswinder Singh Rajput { "misses", "miss", }, 10986470930SIngo Molnar }; 11086470930SIngo Molnar 11106813f6cSJaswinder Singh Rajput #define C(x) PERF_COUNT_HW_CACHE_##x 11206813f6cSJaswinder Singh Rajput #define CACHE_READ (1 << C(OP_READ)) 11306813f6cSJaswinder Singh Rajput #define CACHE_WRITE (1 << C(OP_WRITE)) 11406813f6cSJaswinder Singh Rajput #define CACHE_PREFETCH (1 << C(OP_PREFETCH)) 11506813f6cSJaswinder Singh Rajput #define COP(x) (1 << x) 11606813f6cSJaswinder Singh Rajput 11706813f6cSJaswinder Singh Rajput /* 11806813f6cSJaswinder Singh Rajput * cache operartion stat 11906813f6cSJaswinder Singh Rajput * L1I : Read and prefetch only 12006813f6cSJaswinder Singh Rajput * ITLB and BPU : Read-only 12106813f6cSJaswinder Singh Rajput */ 12206813f6cSJaswinder Singh Rajput static unsigned long hw_cache_stat[C(MAX)] = { 12306813f6cSJaswinder Singh Rajput [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 12406813f6cSJaswinder Singh Rajput [C(L1I)] = (CACHE_READ | CACHE_PREFETCH), 12506813f6cSJaswinder Singh Rajput [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 12606813f6cSJaswinder Singh Rajput [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 12706813f6cSJaswinder Singh Rajput [C(ITLB)] = (CACHE_READ), 12806813f6cSJaswinder Singh Rajput [C(BPU)] = (CACHE_READ), 129*0111919dSJiri Olsa [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 13006813f6cSJaswinder Singh Rajput }; 13106813f6cSJaswinder Singh Rajput 1326b58e7f1SUlrich Drepper #define for_each_subsystem(sys_dir, sys_dirent, sys_next) \ 133f6bdafefSJason Baron while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ 1346b58e7f1SUlrich Drepper if (sys_dirent.d_type == DT_DIR && \ 135f6bdafefSJason Baron (strcmp(sys_dirent.d_name, ".")) && \ 136f6bdafefSJason Baron (strcmp(sys_dirent.d_name, ".."))) 137f6bdafefSJason Baron 138ae07b63fSPeter Zijlstra static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir) 139ae07b63fSPeter Zijlstra { 140ae07b63fSPeter Zijlstra char evt_path[MAXPATHLEN]; 141ae07b63fSPeter Zijlstra int fd; 142ae07b63fSPeter Zijlstra 143ae07b63fSPeter Zijlstra snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 144ae07b63fSPeter Zijlstra sys_dir->d_name, evt_dir->d_name); 145ae07b63fSPeter Zijlstra fd = open(evt_path, O_RDONLY); 146ae07b63fSPeter Zijlstra if (fd < 0) 147ae07b63fSPeter Zijlstra return -EINVAL; 148ae07b63fSPeter Zijlstra close(fd); 149ae07b63fSPeter Zijlstra 150ae07b63fSPeter Zijlstra return 0; 151ae07b63fSPeter Zijlstra } 152ae07b63fSPeter Zijlstra 1536b58e7f1SUlrich Drepper #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) \ 154f6bdafefSJason Baron while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \ 1556b58e7f1SUlrich Drepper if (evt_dirent.d_type == DT_DIR && \ 156f6bdafefSJason Baron (strcmp(evt_dirent.d_name, ".")) && \ 157ae07b63fSPeter Zijlstra (strcmp(evt_dirent.d_name, "..")) && \ 158ae07b63fSPeter Zijlstra (!tp_event_has_id(&sys_dirent, &evt_dirent))) 159f6bdafefSJason Baron 160270bbbe8SLi Zefan #define MAX_EVENT_LENGTH 512 161f6bdafefSJason Baron 162f6bdafefSJason Baron 1631ef2ed10SFrederic Weisbecker struct tracepoint_path *tracepoint_id_to_path(u64 config) 164f6bdafefSJason Baron { 1651ef2ed10SFrederic Weisbecker struct tracepoint_path *path = NULL; 166f6bdafefSJason Baron DIR *sys_dir, *evt_dir; 167f6bdafefSJason Baron struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 168f6bdafefSJason Baron char id_buf[4]; 169725b1368SEric Dumazet int fd; 170f6bdafefSJason Baron u64 id; 171f6bdafefSJason Baron char evt_path[MAXPATHLEN]; 172725b1368SEric Dumazet char dir_path[MAXPATHLEN]; 173f6bdafefSJason Baron 174549104f2SClark Williams if (debugfs_valid_mountpoint(debugfs_path)) 1751ef2ed10SFrederic Weisbecker return NULL; 176f6bdafefSJason Baron 1775beeded1SJason Baron sys_dir = opendir(debugfs_path); 178f6bdafefSJason Baron if (!sys_dir) 179725b1368SEric Dumazet return NULL; 180f6bdafefSJason Baron 1816b58e7f1SUlrich Drepper for_each_subsystem(sys_dir, sys_dirent, sys_next) { 182725b1368SEric Dumazet 183725b1368SEric Dumazet snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 184725b1368SEric Dumazet sys_dirent.d_name); 185725b1368SEric Dumazet evt_dir = opendir(dir_path); 186725b1368SEric Dumazet if (!evt_dir) 1876b58e7f1SUlrich Drepper continue; 188725b1368SEric Dumazet 1896b58e7f1SUlrich Drepper for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 190725b1368SEric Dumazet 191725b1368SEric Dumazet snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, 192f6bdafefSJason Baron evt_dirent.d_name); 193725b1368SEric Dumazet fd = open(evt_path, O_RDONLY); 194f6bdafefSJason Baron if (fd < 0) 195f6bdafefSJason Baron continue; 196f6bdafefSJason Baron if (read(fd, id_buf, sizeof(id_buf)) < 0) { 197f6bdafefSJason Baron close(fd); 198f6bdafefSJason Baron continue; 199f6bdafefSJason Baron } 200f6bdafefSJason Baron close(fd); 201f6bdafefSJason Baron id = atoll(id_buf); 202f6bdafefSJason Baron if (id == config) { 203f6bdafefSJason Baron closedir(evt_dir); 204f6bdafefSJason Baron closedir(sys_dir); 20559b4caebSJulia Lawall path = zalloc(sizeof(*path)); 2061ef2ed10SFrederic Weisbecker path->system = malloc(MAX_EVENT_LENGTH); 2071ef2ed10SFrederic Weisbecker if (!path->system) { 2081ef2ed10SFrederic Weisbecker free(path); 2091ef2ed10SFrederic Weisbecker return NULL; 2101ef2ed10SFrederic Weisbecker } 2111ef2ed10SFrederic Weisbecker path->name = malloc(MAX_EVENT_LENGTH); 2121ef2ed10SFrederic Weisbecker if (!path->name) { 2131ef2ed10SFrederic Weisbecker free(path->system); 2141ef2ed10SFrederic Weisbecker free(path); 2151ef2ed10SFrederic Weisbecker return NULL; 2161ef2ed10SFrederic Weisbecker } 2171ef2ed10SFrederic Weisbecker strncpy(path->system, sys_dirent.d_name, 2181ef2ed10SFrederic Weisbecker MAX_EVENT_LENGTH); 2191ef2ed10SFrederic Weisbecker strncpy(path->name, evt_dirent.d_name, 2201ef2ed10SFrederic Weisbecker MAX_EVENT_LENGTH); 2211ef2ed10SFrederic Weisbecker return path; 222f6bdafefSJason Baron } 223f6bdafefSJason Baron } 224f6bdafefSJason Baron closedir(evt_dir); 225f6bdafefSJason Baron } 226f6bdafefSJason Baron 227f6bdafefSJason Baron closedir(sys_dir); 2281ef2ed10SFrederic Weisbecker return NULL; 2291ef2ed10SFrederic Weisbecker } 2301ef2ed10SFrederic Weisbecker 2311ef2ed10SFrederic Weisbecker #define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1) 2321ef2ed10SFrederic Weisbecker static const char *tracepoint_id_to_name(u64 config) 2331ef2ed10SFrederic Weisbecker { 2341ef2ed10SFrederic Weisbecker static char buf[TP_PATH_LEN]; 2351ef2ed10SFrederic Weisbecker struct tracepoint_path *path; 2361ef2ed10SFrederic Weisbecker 2371ef2ed10SFrederic Weisbecker path = tracepoint_id_to_path(config); 2381ef2ed10SFrederic Weisbecker if (path) { 2391ef2ed10SFrederic Weisbecker snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name); 2401ef2ed10SFrederic Weisbecker free(path->name); 2411ef2ed10SFrederic Weisbecker free(path->system); 2421ef2ed10SFrederic Weisbecker free(path); 2431ef2ed10SFrederic Weisbecker } else 2441ef2ed10SFrederic Weisbecker snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown"); 2451ef2ed10SFrederic Weisbecker 2461ef2ed10SFrederic Weisbecker return buf; 247f6bdafefSJason Baron } 248f6bdafefSJason Baron 24906813f6cSJaswinder Singh Rajput static int is_cache_op_valid(u8 cache_type, u8 cache_op) 25006813f6cSJaswinder Singh Rajput { 25106813f6cSJaswinder Singh Rajput if (hw_cache_stat[cache_type] & COP(cache_op)) 25206813f6cSJaswinder Singh Rajput return 1; /* valid */ 25306813f6cSJaswinder Singh Rajput else 25406813f6cSJaswinder Singh Rajput return 0; /* invalid */ 25506813f6cSJaswinder Singh Rajput } 25606813f6cSJaswinder Singh Rajput 257e5c59547SJaswinder Singh Rajput static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result) 258e5c59547SJaswinder Singh Rajput { 259e5c59547SJaswinder Singh Rajput static char name[50]; 260e5c59547SJaswinder Singh Rajput 261e5c59547SJaswinder Singh Rajput if (cache_result) { 262e5c59547SJaswinder Singh Rajput sprintf(name, "%s-%s-%s", hw_cache[cache_type][0], 263e5c59547SJaswinder Singh Rajput hw_cache_op[cache_op][0], 264e5c59547SJaswinder Singh Rajput hw_cache_result[cache_result][0]); 265e5c59547SJaswinder Singh Rajput } else { 266e5c59547SJaswinder Singh Rajput sprintf(name, "%s-%s", hw_cache[cache_type][0], 267e5c59547SJaswinder Singh Rajput hw_cache_op[cache_op][1]); 268e5c59547SJaswinder Singh Rajput } 269e5c59547SJaswinder Singh Rajput 270e5c59547SJaswinder Singh Rajput return name; 271e5c59547SJaswinder Singh Rajput } 272e5c59547SJaswinder Singh Rajput 2731424dc96SDavid Ahern const char *event_type(int type) 2741424dc96SDavid Ahern { 2751424dc96SDavid Ahern switch (type) { 2761424dc96SDavid Ahern case PERF_TYPE_HARDWARE: 2771424dc96SDavid Ahern return "hardware"; 2781424dc96SDavid Ahern 2791424dc96SDavid Ahern case PERF_TYPE_SOFTWARE: 2801424dc96SDavid Ahern return "software"; 2811424dc96SDavid Ahern 2821424dc96SDavid Ahern case PERF_TYPE_TRACEPOINT: 2831424dc96SDavid Ahern return "tracepoint"; 2841424dc96SDavid Ahern 2851424dc96SDavid Ahern case PERF_TYPE_HW_CACHE: 2861424dc96SDavid Ahern return "hardware-cache"; 2871424dc96SDavid Ahern 2881424dc96SDavid Ahern default: 2891424dc96SDavid Ahern break; 2901424dc96SDavid Ahern } 2911424dc96SDavid Ahern 2921424dc96SDavid Ahern return "unknown"; 2931424dc96SDavid Ahern } 2941424dc96SDavid Ahern 29569aad6f1SArnaldo Carvalho de Melo const char *event_name(struct perf_evsel *evsel) 29686470930SIngo Molnar { 29769aad6f1SArnaldo Carvalho de Melo u64 config = evsel->attr.config; 29869aad6f1SArnaldo Carvalho de Melo int type = evsel->attr.type; 2998f18aec5SPeter Zijlstra 300f0c55bcfSStephane Eranian if (evsel->name) 301f0c55bcfSStephane Eranian return evsel->name; 302f0c55bcfSStephane Eranian 3038f18aec5SPeter Zijlstra return __event_name(type, config); 3048f18aec5SPeter Zijlstra } 3058f18aec5SPeter Zijlstra 30683a0944fSIngo Molnar const char *__event_name(int type, u64 config) 3078f18aec5SPeter Zijlstra { 30886470930SIngo Molnar static char buf[32]; 30986470930SIngo Molnar 3108f18aec5SPeter Zijlstra if (type == PERF_TYPE_RAW) { 3119486aa38SArnaldo Carvalho de Melo sprintf(buf, "raw 0x%" PRIx64, config); 31286470930SIngo Molnar return buf; 31386470930SIngo Molnar } 31486470930SIngo Molnar 31586470930SIngo Molnar switch (type) { 31686470930SIngo Molnar case PERF_TYPE_HARDWARE: 3171fc570adSIngo Molnar if (config < PERF_COUNT_HW_MAX && hw_event_names[config]) 31886470930SIngo Molnar return hw_event_names[config]; 31986470930SIngo Molnar return "unknown-hardware"; 32086470930SIngo Molnar 32186470930SIngo Molnar case PERF_TYPE_HW_CACHE: { 3229cffa8d5SPaul Mackerras u8 cache_type, cache_op, cache_result; 32386470930SIngo Molnar 32486470930SIngo Molnar cache_type = (config >> 0) & 0xff; 32586470930SIngo Molnar if (cache_type > PERF_COUNT_HW_CACHE_MAX) 32686470930SIngo Molnar return "unknown-ext-hardware-cache-type"; 32786470930SIngo Molnar 32886470930SIngo Molnar cache_op = (config >> 8) & 0xff; 32986470930SIngo Molnar if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX) 33086470930SIngo Molnar return "unknown-ext-hardware-cache-op"; 33186470930SIngo Molnar 33286470930SIngo Molnar cache_result = (config >> 16) & 0xff; 33386470930SIngo Molnar if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX) 33486470930SIngo Molnar return "unknown-ext-hardware-cache-result"; 33586470930SIngo Molnar 33606813f6cSJaswinder Singh Rajput if (!is_cache_op_valid(cache_type, cache_op)) 33706813f6cSJaswinder Singh Rajput return "invalid-cache"; 33886470930SIngo Molnar 339e5c59547SJaswinder Singh Rajput return event_cache_name(cache_type, cache_op, cache_result); 34086470930SIngo Molnar } 34186470930SIngo Molnar 34286470930SIngo Molnar case PERF_TYPE_SOFTWARE: 3431fc570adSIngo Molnar if (config < PERF_COUNT_SW_MAX && sw_event_names[config]) 34486470930SIngo Molnar return sw_event_names[config]; 34586470930SIngo Molnar return "unknown-software"; 34686470930SIngo Molnar 347f6bdafefSJason Baron case PERF_TYPE_TRACEPOINT: 348f6bdafefSJason Baron return tracepoint_id_to_name(config); 349f6bdafefSJason Baron 35086470930SIngo Molnar default: 35186470930SIngo Molnar break; 35286470930SIngo Molnar } 35386470930SIngo Molnar 35486470930SIngo Molnar return "unknown"; 35586470930SIngo Molnar } 35686470930SIngo Molnar 35783a0944fSIngo Molnar static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size) 35886470930SIngo Molnar { 35986470930SIngo Molnar int i, j; 36061c45981SPaul Mackerras int n, longest = -1; 36186470930SIngo Molnar 36286470930SIngo Molnar for (i = 0; i < size; i++) { 36361c45981SPaul Mackerras for (j = 0; j < MAX_ALIASES && names[i][j]; j++) { 36461c45981SPaul Mackerras n = strlen(names[i][j]); 36561c45981SPaul Mackerras if (n > longest && !strncasecmp(*str, names[i][j], n)) 36661c45981SPaul Mackerras longest = n; 36761c45981SPaul Mackerras } 36861c45981SPaul Mackerras if (longest > 0) { 36961c45981SPaul Mackerras *str += longest; 37086470930SIngo Molnar return i; 37186470930SIngo Molnar } 37286470930SIngo Molnar } 37386470930SIngo Molnar 3748953645fSIngo Molnar return -1; 37586470930SIngo Molnar } 37686470930SIngo Molnar 377bcd3279fSFrederic Weisbecker static enum event_result 378cdd6c482SIngo Molnar parse_generic_hw_event(const char **str, struct perf_event_attr *attr) 37986470930SIngo Molnar { 38061c45981SPaul Mackerras const char *s = *str; 38161c45981SPaul Mackerras int cache_type = -1, cache_op = -1, cache_result = -1; 38286470930SIngo Molnar 38361c45981SPaul Mackerras cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX); 38486470930SIngo Molnar /* 38586470930SIngo Molnar * No fallback - if we cannot get a clear cache type 38686470930SIngo Molnar * then bail out: 38786470930SIngo Molnar */ 38886470930SIngo Molnar if (cache_type == -1) 389bcd3279fSFrederic Weisbecker return EVT_FAILED; 39086470930SIngo Molnar 39161c45981SPaul Mackerras while ((cache_op == -1 || cache_result == -1) && *s == '-') { 39261c45981SPaul Mackerras ++s; 39361c45981SPaul Mackerras 39461c45981SPaul Mackerras if (cache_op == -1) { 39561c45981SPaul Mackerras cache_op = parse_aliases(&s, hw_cache_op, 39661c45981SPaul Mackerras PERF_COUNT_HW_CACHE_OP_MAX); 39761c45981SPaul Mackerras if (cache_op >= 0) { 39861c45981SPaul Mackerras if (!is_cache_op_valid(cache_type, cache_op)) 399*0111919dSJiri Olsa return EVT_FAILED; 40061c45981SPaul Mackerras continue; 40161c45981SPaul Mackerras } 40261c45981SPaul Mackerras } 40361c45981SPaul Mackerras 40461c45981SPaul Mackerras if (cache_result == -1) { 40561c45981SPaul Mackerras cache_result = parse_aliases(&s, hw_cache_result, 40661c45981SPaul Mackerras PERF_COUNT_HW_CACHE_RESULT_MAX); 40761c45981SPaul Mackerras if (cache_result >= 0) 40861c45981SPaul Mackerras continue; 40961c45981SPaul Mackerras } 41061c45981SPaul Mackerras 41161c45981SPaul Mackerras /* 41261c45981SPaul Mackerras * Can't parse this as a cache op or result, so back up 41361c45981SPaul Mackerras * to the '-'. 41461c45981SPaul Mackerras */ 41561c45981SPaul Mackerras --s; 41661c45981SPaul Mackerras break; 41761c45981SPaul Mackerras } 41861c45981SPaul Mackerras 41986470930SIngo Molnar /* 42086470930SIngo Molnar * Fall back to reads: 42186470930SIngo Molnar */ 4228953645fSIngo Molnar if (cache_op == -1) 4238953645fSIngo Molnar cache_op = PERF_COUNT_HW_CACHE_OP_READ; 42486470930SIngo Molnar 42586470930SIngo Molnar /* 42686470930SIngo Molnar * Fall back to accesses: 42786470930SIngo Molnar */ 42886470930SIngo Molnar if (cache_result == -1) 42986470930SIngo Molnar cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS; 43086470930SIngo Molnar 43186470930SIngo Molnar attr->config = cache_type | (cache_op << 8) | (cache_result << 16); 43286470930SIngo Molnar attr->type = PERF_TYPE_HW_CACHE; 43386470930SIngo Molnar 43461c45981SPaul Mackerras *str = s; 435bcd3279fSFrederic Weisbecker return EVT_HANDLED; 43686470930SIngo Molnar } 43786470930SIngo Molnar 438bcd3279fSFrederic Weisbecker static enum event_result 439bcd3279fSFrederic Weisbecker parse_single_tracepoint_event(char *sys_name, 440bcd3279fSFrederic Weisbecker const char *evt_name, 441bcd3279fSFrederic Weisbecker unsigned int evt_length, 442cdd6c482SIngo Molnar struct perf_event_attr *attr, 443bcd3279fSFrederic Weisbecker const char **strp) 444bcd3279fSFrederic Weisbecker { 445bcd3279fSFrederic Weisbecker char evt_path[MAXPATHLEN]; 446bcd3279fSFrederic Weisbecker char id_buf[4]; 447bcd3279fSFrederic Weisbecker u64 id; 448bcd3279fSFrederic Weisbecker int fd; 449bcd3279fSFrederic Weisbecker 450bcd3279fSFrederic Weisbecker snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 451bcd3279fSFrederic Weisbecker sys_name, evt_name); 452bcd3279fSFrederic Weisbecker 453bcd3279fSFrederic Weisbecker fd = open(evt_path, O_RDONLY); 454bcd3279fSFrederic Weisbecker if (fd < 0) 455bcd3279fSFrederic Weisbecker return EVT_FAILED; 456bcd3279fSFrederic Weisbecker 457bcd3279fSFrederic Weisbecker if (read(fd, id_buf, sizeof(id_buf)) < 0) { 458bcd3279fSFrederic Weisbecker close(fd); 459bcd3279fSFrederic Weisbecker return EVT_FAILED; 460bcd3279fSFrederic Weisbecker } 461bcd3279fSFrederic Weisbecker 462bcd3279fSFrederic Weisbecker close(fd); 463bcd3279fSFrederic Weisbecker id = atoll(id_buf); 464bcd3279fSFrederic Weisbecker attr->config = id; 465bcd3279fSFrederic Weisbecker attr->type = PERF_TYPE_TRACEPOINT; 4664c635a4eSCorey Ashford *strp += strlen(sys_name) + evt_length + 1; /* + 1 for the ':' */ 467bcd3279fSFrederic Weisbecker 4685710fcadSStephane Eranian attr->sample_type |= PERF_SAMPLE_RAW; 4695710fcadSStephane Eranian attr->sample_type |= PERF_SAMPLE_TIME; 4705710fcadSStephane Eranian attr->sample_type |= PERF_SAMPLE_CPU; 4715710fcadSStephane Eranian 4725710fcadSStephane Eranian attr->sample_period = 1; 4735710fcadSStephane Eranian 4745710fcadSStephane Eranian 475bcd3279fSFrederic Weisbecker return EVT_HANDLED; 476bcd3279fSFrederic Weisbecker } 477bcd3279fSFrederic Weisbecker 478bcd3279fSFrederic Weisbecker /* sys + ':' + event + ':' + flags*/ 479bcd3279fSFrederic Weisbecker #define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128) 480bcd3279fSFrederic Weisbecker static enum event_result 48117ea1b70SArnaldo Carvalho de Melo parse_multiple_tracepoint_event(const struct option *opt, char *sys_name, 48217ea1b70SArnaldo Carvalho de Melo const char *evt_exp, char *flags) 483bcd3279fSFrederic Weisbecker { 484bcd3279fSFrederic Weisbecker char evt_path[MAXPATHLEN]; 485bcd3279fSFrederic Weisbecker struct dirent *evt_ent; 486bcd3279fSFrederic Weisbecker DIR *evt_dir; 487bcd3279fSFrederic Weisbecker 488bcd3279fSFrederic Weisbecker snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name); 489bcd3279fSFrederic Weisbecker evt_dir = opendir(evt_path); 490bcd3279fSFrederic Weisbecker 491bcd3279fSFrederic Weisbecker if (!evt_dir) { 492bcd3279fSFrederic Weisbecker perror("Can't open event dir"); 493bcd3279fSFrederic Weisbecker return EVT_FAILED; 494bcd3279fSFrederic Weisbecker } 495bcd3279fSFrederic Weisbecker 496bcd3279fSFrederic Weisbecker while ((evt_ent = readdir(evt_dir))) { 497bcd3279fSFrederic Weisbecker char event_opt[MAX_EVOPT_LEN + 1]; 498bcd3279fSFrederic Weisbecker int len; 499bcd3279fSFrederic Weisbecker 500bcd3279fSFrederic Weisbecker if (!strcmp(evt_ent->d_name, ".") 501bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "..") 502bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "enable") 503bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "filter")) 504bcd3279fSFrederic Weisbecker continue; 505bcd3279fSFrederic Weisbecker 506fb1d2edfSMasami Hiramatsu if (!strglobmatch(evt_ent->d_name, evt_exp)) 507fb1d2edfSMasami Hiramatsu continue; 508fb1d2edfSMasami Hiramatsu 509180570fdSUlrich Drepper len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s%s%s", sys_name, 510180570fdSUlrich Drepper evt_ent->d_name, flags ? ":" : "", 511180570fdSUlrich Drepper flags ?: ""); 512bcd3279fSFrederic Weisbecker if (len < 0) 513bcd3279fSFrederic Weisbecker return EVT_FAILED; 514bcd3279fSFrederic Weisbecker 51517ea1b70SArnaldo Carvalho de Melo if (parse_events(opt, event_opt, 0)) 516bcd3279fSFrederic Weisbecker return EVT_FAILED; 517bcd3279fSFrederic Weisbecker } 518bcd3279fSFrederic Weisbecker 519bcd3279fSFrederic Weisbecker return EVT_HANDLED_ALL; 520bcd3279fSFrederic Weisbecker } 521bcd3279fSFrederic Weisbecker 52217ea1b70SArnaldo Carvalho de Melo static enum event_result 52317ea1b70SArnaldo Carvalho de Melo parse_tracepoint_event(const struct option *opt, const char **strp, 524cdd6c482SIngo Molnar struct perf_event_attr *attr) 525f6bdafefSJason Baron { 526f6bdafefSJason Baron const char *evt_name; 5274c635a4eSCorey Ashford char *flags = NULL, *comma_loc; 528f6bdafefSJason Baron char sys_name[MAX_EVENT_LENGTH]; 529f6bdafefSJason Baron unsigned int sys_length, evt_length; 530f6bdafefSJason Baron 531549104f2SClark Williams if (debugfs_valid_mountpoint(debugfs_path)) 532f6bdafefSJason Baron return 0; 533f6bdafefSJason Baron 534f6bdafefSJason Baron evt_name = strchr(*strp, ':'); 535f6bdafefSJason Baron if (!evt_name) 536bcd3279fSFrederic Weisbecker return EVT_FAILED; 537f6bdafefSJason Baron 538f6bdafefSJason Baron sys_length = evt_name - *strp; 539f6bdafefSJason Baron if (sys_length >= MAX_EVENT_LENGTH) 540f6bdafefSJason Baron return 0; 541f6bdafefSJason Baron 542f6bdafefSJason Baron strncpy(sys_name, *strp, sys_length); 543f6bdafefSJason Baron sys_name[sys_length] = '\0'; 544f6bdafefSJason Baron evt_name = evt_name + 1; 5453a9f131fSFrederic Weisbecker 5464c635a4eSCorey Ashford comma_loc = strchr(evt_name, ','); 5474c635a4eSCorey Ashford if (comma_loc) { 5484c635a4eSCorey Ashford /* take the event name up to the comma */ 5494c635a4eSCorey Ashford evt_name = strndup(evt_name, comma_loc - evt_name); 5504c635a4eSCorey Ashford } 5513a9f131fSFrederic Weisbecker flags = strchr(evt_name, ':'); 5523a9f131fSFrederic Weisbecker if (flags) { 5531fc35b29SIngo Molnar /* split it out: */ 5541fc35b29SIngo Molnar evt_name = strndup(evt_name, flags - evt_name); 5553a9f131fSFrederic Weisbecker flags++; 5563a9f131fSFrederic Weisbecker } 5573a9f131fSFrederic Weisbecker 558f6bdafefSJason Baron evt_length = strlen(evt_name); 559f6bdafefSJason Baron if (evt_length >= MAX_EVENT_LENGTH) 560bcd3279fSFrederic Weisbecker return EVT_FAILED; 561fb1d2edfSMasami Hiramatsu if (strpbrk(evt_name, "*?")) { 562dd9a9ad5SArnaldo Carvalho de Melo *strp += strlen(sys_name) + evt_length + 1; /* 1 == the ':' */ 56317ea1b70SArnaldo Carvalho de Melo return parse_multiple_tracepoint_event(opt, sys_name, evt_name, 564fb1d2edfSMasami Hiramatsu flags); 565f006d25aSHan Pingtian } else { 566bcd3279fSFrederic Weisbecker return parse_single_tracepoint_event(sys_name, evt_name, 567bdef3b02SFrederic Weisbecker evt_length, attr, strp); 568f6bdafefSJason Baron } 569f006d25aSHan Pingtian } 570f6bdafefSJason Baron 5711b290d67SFrederic Weisbecker static enum event_result 5721b290d67SFrederic Weisbecker parse_breakpoint_type(const char *type, const char **strp, 5731b290d67SFrederic Weisbecker struct perf_event_attr *attr) 5741b290d67SFrederic Weisbecker { 5751b290d67SFrederic Weisbecker int i; 5761b290d67SFrederic Weisbecker 5771b290d67SFrederic Weisbecker for (i = 0; i < 3; i++) { 5781b290d67SFrederic Weisbecker if (!type[i]) 5791b290d67SFrederic Weisbecker break; 5801b290d67SFrederic Weisbecker 5811b290d67SFrederic Weisbecker switch (type[i]) { 5821b290d67SFrederic Weisbecker case 'r': 5831b290d67SFrederic Weisbecker attr->bp_type |= HW_BREAKPOINT_R; 5841b290d67SFrederic Weisbecker break; 5851b290d67SFrederic Weisbecker case 'w': 5861b290d67SFrederic Weisbecker attr->bp_type |= HW_BREAKPOINT_W; 5871b290d67SFrederic Weisbecker break; 5881b290d67SFrederic Weisbecker case 'x': 5891b290d67SFrederic Weisbecker attr->bp_type |= HW_BREAKPOINT_X; 5901b290d67SFrederic Weisbecker break; 5911b290d67SFrederic Weisbecker default: 5921b290d67SFrederic Weisbecker return EVT_FAILED; 5931b290d67SFrederic Weisbecker } 5941b290d67SFrederic Weisbecker } 5951b290d67SFrederic Weisbecker if (!attr->bp_type) /* Default */ 5961b290d67SFrederic Weisbecker attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; 5971b290d67SFrederic Weisbecker 5981b290d67SFrederic Weisbecker *strp = type + i; 5991b290d67SFrederic Weisbecker 6001b290d67SFrederic Weisbecker return EVT_HANDLED; 6011b290d67SFrederic Weisbecker } 6021b290d67SFrederic Weisbecker 6031b290d67SFrederic Weisbecker static enum event_result 6041b290d67SFrederic Weisbecker parse_breakpoint_event(const char **strp, struct perf_event_attr *attr) 6051b290d67SFrederic Weisbecker { 6061b290d67SFrederic Weisbecker const char *target; 6071b290d67SFrederic Weisbecker const char *type; 6081b290d67SFrederic Weisbecker char *endaddr; 6091b290d67SFrederic Weisbecker u64 addr; 6101b290d67SFrederic Weisbecker enum event_result err; 6111b290d67SFrederic Weisbecker 6121b290d67SFrederic Weisbecker target = strchr(*strp, ':'); 6131b290d67SFrederic Weisbecker if (!target) 6141b290d67SFrederic Weisbecker return EVT_FAILED; 6151b290d67SFrederic Weisbecker 6161b290d67SFrederic Weisbecker if (strncmp(*strp, "mem", target - *strp) != 0) 6171b290d67SFrederic Weisbecker return EVT_FAILED; 6181b290d67SFrederic Weisbecker 6191b290d67SFrederic Weisbecker target++; 6201b290d67SFrederic Weisbecker 6211b290d67SFrederic Weisbecker addr = strtoull(target, &endaddr, 0); 6221b290d67SFrederic Weisbecker if (target == endaddr) 6231b290d67SFrederic Weisbecker return EVT_FAILED; 6241b290d67SFrederic Weisbecker 6251b290d67SFrederic Weisbecker attr->bp_addr = addr; 6261b290d67SFrederic Weisbecker *strp = endaddr; 6271b290d67SFrederic Weisbecker 6281b290d67SFrederic Weisbecker type = strchr(target, ':'); 6291b290d67SFrederic Weisbecker 6301b290d67SFrederic Weisbecker /* If no type is defined, just rw as default */ 6311b290d67SFrederic Weisbecker if (!type) { 6321b290d67SFrederic Weisbecker attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; 6331b290d67SFrederic Weisbecker } else { 6341b290d67SFrederic Weisbecker err = parse_breakpoint_type(++type, strp, attr); 6351b290d67SFrederic Weisbecker if (err == EVT_FAILED) 6361b290d67SFrederic Weisbecker return EVT_FAILED; 6371b290d67SFrederic Weisbecker } 6381b290d67SFrederic Weisbecker 639aa59a485SFrederic Weisbecker /* 640aa59a485SFrederic Weisbecker * We should find a nice way to override the access length 641aa59a485SFrederic Weisbecker * Provide some defaults for now 642aa59a485SFrederic Weisbecker */ 643aa59a485SFrederic Weisbecker if (attr->bp_type == HW_BREAKPOINT_X) 644aa59a485SFrederic Weisbecker attr->bp_len = sizeof(long); 645aa59a485SFrederic Weisbecker else 6461b290d67SFrederic Weisbecker attr->bp_len = HW_BREAKPOINT_LEN_4; 647aa59a485SFrederic Weisbecker 6481b290d67SFrederic Weisbecker attr->type = PERF_TYPE_BREAKPOINT; 6491b290d67SFrederic Weisbecker 6501b290d67SFrederic Weisbecker return EVT_HANDLED; 6511b290d67SFrederic Weisbecker } 6521b290d67SFrederic Weisbecker 65374d5b588SJaswinder Singh Rajput static int check_events(const char *str, unsigned int i) 65474d5b588SJaswinder Singh Rajput { 65561c45981SPaul Mackerras int n; 65674d5b588SJaswinder Singh Rajput 65761c45981SPaul Mackerras n = strlen(event_symbols[i].symbol); 658b908debdSIngo Molnar if (!strncasecmp(str, event_symbols[i].symbol, n)) 65961c45981SPaul Mackerras return n; 66061c45981SPaul Mackerras 66161c45981SPaul Mackerras n = strlen(event_symbols[i].alias); 662b908debdSIngo Molnar if (n) { 663b908debdSIngo Molnar if (!strncasecmp(str, event_symbols[i].alias, n)) 66461c45981SPaul Mackerras return n; 665b908debdSIngo Molnar } 666b908debdSIngo Molnar 66761c45981SPaul Mackerras return 0; 66861c45981SPaul Mackerras } 66961c45981SPaul Mackerras 670bcd3279fSFrederic Weisbecker static enum event_result 671cdd6c482SIngo Molnar parse_symbolic_event(const char **strp, struct perf_event_attr *attr) 67261c45981SPaul Mackerras { 67361c45981SPaul Mackerras const char *str = *strp; 67461c45981SPaul Mackerras unsigned int i; 67561c45981SPaul Mackerras int n; 67661c45981SPaul Mackerras 67761c45981SPaul Mackerras for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { 67861c45981SPaul Mackerras n = check_events(str, i); 67961c45981SPaul Mackerras if (n > 0) { 68061c45981SPaul Mackerras attr->type = event_symbols[i].type; 68161c45981SPaul Mackerras attr->config = event_symbols[i].config; 68261c45981SPaul Mackerras *strp = str + n; 683bcd3279fSFrederic Weisbecker return EVT_HANDLED; 68461c45981SPaul Mackerras } 68561c45981SPaul Mackerras } 686bcd3279fSFrederic Weisbecker return EVT_FAILED; 68761c45981SPaul Mackerras } 68861c45981SPaul Mackerras 689bcd3279fSFrederic Weisbecker static enum event_result 690cdd6c482SIngo Molnar parse_raw_event(const char **strp, struct perf_event_attr *attr) 69161c45981SPaul Mackerras { 69261c45981SPaul Mackerras const char *str = *strp; 69361c45981SPaul Mackerras u64 config; 69461c45981SPaul Mackerras int n; 69561c45981SPaul Mackerras 69661c45981SPaul Mackerras if (*str != 'r') 697bcd3279fSFrederic Weisbecker return EVT_FAILED; 69861c45981SPaul Mackerras n = hex2u64(str + 1, &config); 69961c45981SPaul Mackerras if (n > 0) { 70061c45981SPaul Mackerras *strp = str + n + 1; 70161c45981SPaul Mackerras attr->type = PERF_TYPE_RAW; 70261c45981SPaul Mackerras attr->config = config; 703bcd3279fSFrederic Weisbecker return EVT_HANDLED; 70461c45981SPaul Mackerras } 705bcd3279fSFrederic Weisbecker return EVT_FAILED; 70661c45981SPaul Mackerras } 70761c45981SPaul Mackerras 708bcd3279fSFrederic Weisbecker static enum event_result 709cdd6c482SIngo Molnar parse_numeric_event(const char **strp, struct perf_event_attr *attr) 71061c45981SPaul Mackerras { 71161c45981SPaul Mackerras const char *str = *strp; 71261c45981SPaul Mackerras char *endp; 71361c45981SPaul Mackerras unsigned long type; 71461c45981SPaul Mackerras u64 config; 71561c45981SPaul Mackerras 71661c45981SPaul Mackerras type = strtoul(str, &endp, 0); 71761c45981SPaul Mackerras if (endp > str && type < PERF_TYPE_MAX && *endp == ':') { 71861c45981SPaul Mackerras str = endp + 1; 71961c45981SPaul Mackerras config = strtoul(str, &endp, 0); 72061c45981SPaul Mackerras if (endp > str) { 72161c45981SPaul Mackerras attr->type = type; 72261c45981SPaul Mackerras attr->config = config; 72361c45981SPaul Mackerras *strp = endp; 724bcd3279fSFrederic Weisbecker return EVT_HANDLED; 72561c45981SPaul Mackerras } 72661c45981SPaul Mackerras } 727bcd3279fSFrederic Weisbecker return EVT_FAILED; 72861c45981SPaul Mackerras } 72961c45981SPaul Mackerras 730ceb53fbfSIngo Molnar static int 731cdd6c482SIngo Molnar parse_event_modifier(const char **strp, struct perf_event_attr *attr) 73261c45981SPaul Mackerras { 73361c45981SPaul Mackerras const char *str = *strp; 734ab608344SPeter Zijlstra int exclude = 0; 735ab608344SPeter Zijlstra int eu = 0, ek = 0, eh = 0, precise = 0; 73661c45981SPaul Mackerras 737ceb53fbfSIngo Molnar if (!*str) 73861c45981SPaul Mackerras return 0; 739ceb53fbfSIngo Molnar 74094692349SStephane Eranian if (*str == ',') 74194692349SStephane Eranian return 0; 74294692349SStephane Eranian 743ceb53fbfSIngo Molnar if (*str++ != ':') 744ceb53fbfSIngo Molnar return -1; 745ceb53fbfSIngo Molnar 74661c45981SPaul Mackerras while (*str) { 747ab608344SPeter Zijlstra if (*str == 'u') { 748ab608344SPeter Zijlstra if (!exclude) 749ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 75061c45981SPaul Mackerras eu = 0; 751ab608344SPeter Zijlstra } else if (*str == 'k') { 752ab608344SPeter Zijlstra if (!exclude) 753ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 75461c45981SPaul Mackerras ek = 0; 755ab608344SPeter Zijlstra } else if (*str == 'h') { 756ab608344SPeter Zijlstra if (!exclude) 757ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 75861c45981SPaul Mackerras eh = 0; 759ab608344SPeter Zijlstra } else if (*str == 'p') { 760ab608344SPeter Zijlstra precise++; 761ab608344SPeter Zijlstra } else 76261c45981SPaul Mackerras break; 763ab608344SPeter Zijlstra 76461c45981SPaul Mackerras ++str; 76561c45981SPaul Mackerras } 766ceb53fbfSIngo Molnar if (str < *strp + 2) 767ceb53fbfSIngo Molnar return -1; 768ceb53fbfSIngo Molnar 76961c45981SPaul Mackerras *strp = str; 770ceb53fbfSIngo Molnar 77161c45981SPaul Mackerras attr->exclude_user = eu; 77261c45981SPaul Mackerras attr->exclude_kernel = ek; 77361c45981SPaul Mackerras attr->exclude_hv = eh; 774ab608344SPeter Zijlstra attr->precise_ip = precise; 775ceb53fbfSIngo Molnar 77674d5b588SJaswinder Singh Rajput return 0; 77774d5b588SJaswinder Singh Rajput } 77874d5b588SJaswinder Singh Rajput 77986470930SIngo Molnar /* 78086470930SIngo Molnar * Each event can have multiple symbolic names. 78186470930SIngo Molnar * Symbolic names are (almost) exactly matched. 78286470930SIngo Molnar */ 783bcd3279fSFrederic Weisbecker static enum event_result 78417ea1b70SArnaldo Carvalho de Melo parse_event_symbols(const struct option *opt, const char **str, 78517ea1b70SArnaldo Carvalho de Melo struct perf_event_attr *attr) 78686470930SIngo Molnar { 787bcd3279fSFrederic Weisbecker enum event_result ret; 78886470930SIngo Molnar 78917ea1b70SArnaldo Carvalho de Melo ret = parse_tracepoint_event(opt, str, attr); 790bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 791bcd3279fSFrederic Weisbecker goto modifier; 792bcd3279fSFrederic Weisbecker 793bcd3279fSFrederic Weisbecker ret = parse_raw_event(str, attr); 794bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 795bcd3279fSFrederic Weisbecker goto modifier; 796bcd3279fSFrederic Weisbecker 797bcd3279fSFrederic Weisbecker ret = parse_numeric_event(str, attr); 798bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 799bcd3279fSFrederic Weisbecker goto modifier; 800bcd3279fSFrederic Weisbecker 801bcd3279fSFrederic Weisbecker ret = parse_symbolic_event(str, attr); 802bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 803bcd3279fSFrederic Weisbecker goto modifier; 804bcd3279fSFrederic Weisbecker 805bcd3279fSFrederic Weisbecker ret = parse_generic_hw_event(str, attr); 806bcd3279fSFrederic Weisbecker if (ret != EVT_FAILED) 807bcd3279fSFrederic Weisbecker goto modifier; 808bcd3279fSFrederic Weisbecker 8091b290d67SFrederic Weisbecker ret = parse_breakpoint_event(str, attr); 8101b290d67SFrederic Weisbecker if (ret != EVT_FAILED) 8111b290d67SFrederic Weisbecker goto modifier; 8121b290d67SFrederic Weisbecker 81385df6f68SMarti Raudsepp fprintf(stderr, "invalid or unsupported event: '%s'\n", *str); 81485df6f68SMarti Raudsepp fprintf(stderr, "Run 'perf list' for a list of valid events\n"); 815bcd3279fSFrederic Weisbecker return EVT_FAILED; 816bcd3279fSFrederic Weisbecker 817bcd3279fSFrederic Weisbecker modifier: 818ceb53fbfSIngo Molnar if (parse_event_modifier(str, attr) < 0) { 819ceb53fbfSIngo Molnar fprintf(stderr, "invalid event modifier: '%s'\n", *str); 820ceb53fbfSIngo Molnar fprintf(stderr, "Run 'perf list' for a list of valid events and modifiers\n"); 821ceb53fbfSIngo Molnar 822ceb53fbfSIngo Molnar return EVT_FAILED; 823ceb53fbfSIngo Molnar } 82486470930SIngo Molnar 825bcd3279fSFrederic Weisbecker return ret; 82686470930SIngo Molnar } 82786470930SIngo Molnar 828361c99a6SArnaldo Carvalho de Melo int parse_events(const struct option *opt, const char *str, int unset __used) 82986470930SIngo Molnar { 830361c99a6SArnaldo Carvalho de Melo struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 831cdd6c482SIngo Molnar struct perf_event_attr attr; 832bcd3279fSFrederic Weisbecker enum event_result ret; 833f0c55bcfSStephane Eranian const char *ostr; 83486470930SIngo Molnar 83561c45981SPaul Mackerras for (;;) { 836f0c55bcfSStephane Eranian ostr = str; 83761c45981SPaul Mackerras memset(&attr, 0, sizeof(attr)); 83817ea1b70SArnaldo Carvalho de Melo ret = parse_event_symbols(opt, &str, &attr); 839bcd3279fSFrederic Weisbecker if (ret == EVT_FAILED) 84061c45981SPaul Mackerras return -1; 84161c45981SPaul Mackerras 84261c45981SPaul Mackerras if (!(*str == 0 || *str == ',' || isspace(*str))) 84361c45981SPaul Mackerras return -1; 84486470930SIngo Molnar 845bcd3279fSFrederic Weisbecker if (ret != EVT_HANDLED_ALL) { 84669aad6f1SArnaldo Carvalho de Melo struct perf_evsel *evsel; 847361c99a6SArnaldo Carvalho de Melo evsel = perf_evsel__new(&attr, evlist->nr_entries); 84869aad6f1SArnaldo Carvalho de Melo if (evsel == NULL) 84969aad6f1SArnaldo Carvalho de Melo return -1; 850361c99a6SArnaldo Carvalho de Melo perf_evlist__add(evlist, evsel); 851f0c55bcfSStephane Eranian 852f0c55bcfSStephane Eranian evsel->name = calloc(str - ostr + 1, 1); 853f0c55bcfSStephane Eranian if (!evsel->name) 854f0c55bcfSStephane Eranian return -1; 855f0c55bcfSStephane Eranian strncpy(evsel->name, ostr, str - ostr); 856bcd3279fSFrederic Weisbecker } 85786470930SIngo Molnar 85861c45981SPaul Mackerras if (*str == 0) 85961c45981SPaul Mackerras break; 86061c45981SPaul Mackerras if (*str == ',') 86161c45981SPaul Mackerras ++str; 86261c45981SPaul Mackerras while (isspace(*str)) 86361c45981SPaul Mackerras ++str; 86486470930SIngo Molnar } 86586470930SIngo Molnar 86686470930SIngo Molnar return 0; 86786470930SIngo Molnar } 86886470930SIngo Molnar 869361c99a6SArnaldo Carvalho de Melo int parse_filter(const struct option *opt, const char *str, 870c171b552SLi Zefan int unset __used) 871c171b552SLi Zefan { 872361c99a6SArnaldo Carvalho de Melo struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 87369aad6f1SArnaldo Carvalho de Melo struct perf_evsel *last = NULL; 874c171b552SLi Zefan 875361c99a6SArnaldo Carvalho de Melo if (evlist->nr_entries > 0) 876361c99a6SArnaldo Carvalho de Melo last = list_entry(evlist->entries.prev, struct perf_evsel, node); 87769aad6f1SArnaldo Carvalho de Melo 87869aad6f1SArnaldo Carvalho de Melo if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) { 879c171b552SLi Zefan fprintf(stderr, 880c171b552SLi Zefan "-F option should follow a -e tracepoint option\n"); 881c171b552SLi Zefan return -1; 882c171b552SLi Zefan } 883c171b552SLi Zefan 88469aad6f1SArnaldo Carvalho de Melo last->filter = strdup(str); 88569aad6f1SArnaldo Carvalho de Melo if (last->filter == NULL) { 886c171b552SLi Zefan fprintf(stderr, "not enough memory to hold filter string\n"); 887c171b552SLi Zefan return -1; 888c171b552SLi Zefan } 889c171b552SLi Zefan 890c171b552SLi Zefan return 0; 891c171b552SLi Zefan } 892c171b552SLi Zefan 89386470930SIngo Molnar static const char * const event_type_descriptors[] = { 89486470930SIngo Molnar "Hardware event", 89586470930SIngo Molnar "Software event", 89686470930SIngo Molnar "Tracepoint event", 89786470930SIngo Molnar "Hardware cache event", 89841bdcb23SLiming Wang "Raw hardware event descriptor", 89941bdcb23SLiming Wang "Hardware breakpoint", 90086470930SIngo Molnar }; 90186470930SIngo Molnar 90286470930SIngo Molnar /* 903f6bdafefSJason Baron * Print the events from <debugfs_mount_point>/tracing/events 904f6bdafefSJason Baron */ 905f6bdafefSJason Baron 906668b8788SArnaldo Carvalho de Melo void print_tracepoint_events(const char *subsys_glob, const char *event_glob) 907f6bdafefSJason Baron { 908f6bdafefSJason Baron DIR *sys_dir, *evt_dir; 909f6bdafefSJason Baron struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 910f6bdafefSJason Baron char evt_path[MAXPATHLEN]; 911725b1368SEric Dumazet char dir_path[MAXPATHLEN]; 912f6bdafefSJason Baron 913549104f2SClark Williams if (debugfs_valid_mountpoint(debugfs_path)) 914f6bdafefSJason Baron return; 915f6bdafefSJason Baron 9165beeded1SJason Baron sys_dir = opendir(debugfs_path); 917f6bdafefSJason Baron if (!sys_dir) 918725b1368SEric Dumazet return; 919f6bdafefSJason Baron 9206b58e7f1SUlrich Drepper for_each_subsystem(sys_dir, sys_dirent, sys_next) { 921668b8788SArnaldo Carvalho de Melo if (subsys_glob != NULL && 922668b8788SArnaldo Carvalho de Melo !strglobmatch(sys_dirent.d_name, subsys_glob)) 923668b8788SArnaldo Carvalho de Melo continue; 924725b1368SEric Dumazet 925725b1368SEric Dumazet snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 926725b1368SEric Dumazet sys_dirent.d_name); 927725b1368SEric Dumazet evt_dir = opendir(dir_path); 928725b1368SEric Dumazet if (!evt_dir) 9296b58e7f1SUlrich Drepper continue; 930725b1368SEric Dumazet 9316b58e7f1SUlrich Drepper for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 932668b8788SArnaldo Carvalho de Melo if (event_glob != NULL && 933668b8788SArnaldo Carvalho de Melo !strglobmatch(evt_dirent.d_name, event_glob)) 934668b8788SArnaldo Carvalho de Melo continue; 935668b8788SArnaldo Carvalho de Melo 936f6bdafefSJason Baron snprintf(evt_path, MAXPATHLEN, "%s:%s", 937f6bdafefSJason Baron sys_dirent.d_name, evt_dirent.d_name); 938947b4ad1SIngo Molnar printf(" %-50s [%s]\n", evt_path, 93941bdcb23SLiming Wang event_type_descriptors[PERF_TYPE_TRACEPOINT]); 940f6bdafefSJason Baron } 941f6bdafefSJason Baron closedir(evt_dir); 942f6bdafefSJason Baron } 943f6bdafefSJason Baron closedir(sys_dir); 944f6bdafefSJason Baron } 945f6bdafefSJason Baron 946f6bdafefSJason Baron /* 94720c457b8SThomas Renninger * Check whether event is in <debugfs_mount_point>/tracing/events 94820c457b8SThomas Renninger */ 94920c457b8SThomas Renninger 95020c457b8SThomas Renninger int is_valid_tracepoint(const char *event_string) 95120c457b8SThomas Renninger { 95220c457b8SThomas Renninger DIR *sys_dir, *evt_dir; 95320c457b8SThomas Renninger struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 95420c457b8SThomas Renninger char evt_path[MAXPATHLEN]; 95520c457b8SThomas Renninger char dir_path[MAXPATHLEN]; 95620c457b8SThomas Renninger 95720c457b8SThomas Renninger if (debugfs_valid_mountpoint(debugfs_path)) 95820c457b8SThomas Renninger return 0; 95920c457b8SThomas Renninger 96020c457b8SThomas Renninger sys_dir = opendir(debugfs_path); 96120c457b8SThomas Renninger if (!sys_dir) 96220c457b8SThomas Renninger return 0; 96320c457b8SThomas Renninger 96420c457b8SThomas Renninger for_each_subsystem(sys_dir, sys_dirent, sys_next) { 96520c457b8SThomas Renninger 96620c457b8SThomas Renninger snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 96720c457b8SThomas Renninger sys_dirent.d_name); 96820c457b8SThomas Renninger evt_dir = opendir(dir_path); 96920c457b8SThomas Renninger if (!evt_dir) 97020c457b8SThomas Renninger continue; 97120c457b8SThomas Renninger 97220c457b8SThomas Renninger for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 97320c457b8SThomas Renninger snprintf(evt_path, MAXPATHLEN, "%s:%s", 97420c457b8SThomas Renninger sys_dirent.d_name, evt_dirent.d_name); 97520c457b8SThomas Renninger if (!strcmp(evt_path, event_string)) { 97620c457b8SThomas Renninger closedir(evt_dir); 97720c457b8SThomas Renninger closedir(sys_dir); 97820c457b8SThomas Renninger return 1; 97920c457b8SThomas Renninger } 98020c457b8SThomas Renninger } 98120c457b8SThomas Renninger closedir(evt_dir); 98220c457b8SThomas Renninger } 98320c457b8SThomas Renninger closedir(sys_dir); 98420c457b8SThomas Renninger return 0; 98520c457b8SThomas Renninger } 98620c457b8SThomas Renninger 987668b8788SArnaldo Carvalho de Melo void print_events_type(u8 type) 988668b8788SArnaldo Carvalho de Melo { 989668b8788SArnaldo Carvalho de Melo struct event_symbol *syms = event_symbols; 990668b8788SArnaldo Carvalho de Melo unsigned int i; 991668b8788SArnaldo Carvalho de Melo char name[64]; 992668b8788SArnaldo Carvalho de Melo 993668b8788SArnaldo Carvalho de Melo for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 994668b8788SArnaldo Carvalho de Melo if (type != syms->type) 995668b8788SArnaldo Carvalho de Melo continue; 996668b8788SArnaldo Carvalho de Melo 997668b8788SArnaldo Carvalho de Melo if (strlen(syms->alias)) 998668b8788SArnaldo Carvalho de Melo snprintf(name, sizeof(name), "%s OR %s", 999668b8788SArnaldo Carvalho de Melo syms->symbol, syms->alias); 1000668b8788SArnaldo Carvalho de Melo else 1001668b8788SArnaldo Carvalho de Melo snprintf(name, sizeof(name), "%s", syms->symbol); 1002668b8788SArnaldo Carvalho de Melo 1003947b4ad1SIngo Molnar printf(" %-50s [%s]\n", name, 1004668b8788SArnaldo Carvalho de Melo event_type_descriptors[type]); 1005668b8788SArnaldo Carvalho de Melo } 1006668b8788SArnaldo Carvalho de Melo } 1007668b8788SArnaldo Carvalho de Melo 1008668b8788SArnaldo Carvalho de Melo int print_hwcache_events(const char *event_glob) 1009668b8788SArnaldo Carvalho de Melo { 1010668b8788SArnaldo Carvalho de Melo unsigned int type, op, i, printed = 0; 1011668b8788SArnaldo Carvalho de Melo 1012668b8788SArnaldo Carvalho de Melo for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 1013668b8788SArnaldo Carvalho de Melo for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 1014668b8788SArnaldo Carvalho de Melo /* skip invalid cache type */ 1015668b8788SArnaldo Carvalho de Melo if (!is_cache_op_valid(type, op)) 1016668b8788SArnaldo Carvalho de Melo continue; 1017668b8788SArnaldo Carvalho de Melo 1018668b8788SArnaldo Carvalho de Melo for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { 1019668b8788SArnaldo Carvalho de Melo char *name = event_cache_name(type, op, i); 1020668b8788SArnaldo Carvalho de Melo 1021947b4ad1SIngo Molnar if (event_glob != NULL && !strglobmatch(name, event_glob)) 1022668b8788SArnaldo Carvalho de Melo continue; 1023668b8788SArnaldo Carvalho de Melo 1024947b4ad1SIngo Molnar printf(" %-50s [%s]\n", name, 1025668b8788SArnaldo Carvalho de Melo event_type_descriptors[PERF_TYPE_HW_CACHE]); 1026668b8788SArnaldo Carvalho de Melo ++printed; 1027668b8788SArnaldo Carvalho de Melo } 1028668b8788SArnaldo Carvalho de Melo } 1029668b8788SArnaldo Carvalho de Melo } 1030668b8788SArnaldo Carvalho de Melo 1031668b8788SArnaldo Carvalho de Melo return printed; 1032668b8788SArnaldo Carvalho de Melo } 1033668b8788SArnaldo Carvalho de Melo 1034947b4ad1SIngo Molnar #define MAX_NAME_LEN 100 1035947b4ad1SIngo Molnar 103620c457b8SThomas Renninger /* 103786470930SIngo Molnar * Print the help text for the event symbols: 103886470930SIngo Molnar */ 1039668b8788SArnaldo Carvalho de Melo void print_events(const char *event_glob) 104086470930SIngo Molnar { 1041668b8788SArnaldo Carvalho de Melo unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0; 1042947b4ad1SIngo Molnar struct event_symbol *syms = event_symbols; 1043947b4ad1SIngo Molnar char name[MAX_NAME_LEN]; 104486470930SIngo Molnar 1045689d3018SMarti Raudsepp printf("\n"); 1046689d3018SMarti Raudsepp printf("List of pre-defined events (to be used in -e):\n"); 104786470930SIngo Molnar 104886470930SIngo Molnar for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 104941bdcb23SLiming Wang type = syms->type; 105086470930SIngo Molnar 1051668b8788SArnaldo Carvalho de Melo if (type != prev_type && printed) { 1052689d3018SMarti Raudsepp printf("\n"); 1053668b8788SArnaldo Carvalho de Melo printed = 0; 1054668b8788SArnaldo Carvalho de Melo ntypes_printed++; 1055668b8788SArnaldo Carvalho de Melo } 1056668b8788SArnaldo Carvalho de Melo 1057668b8788SArnaldo Carvalho de Melo if (event_glob != NULL && 1058668b8788SArnaldo Carvalho de Melo !(strglobmatch(syms->symbol, event_glob) || 1059668b8788SArnaldo Carvalho de Melo (syms->alias && strglobmatch(syms->alias, event_glob)))) 1060668b8788SArnaldo Carvalho de Melo continue; 106186470930SIngo Molnar 106274d5b588SJaswinder Singh Rajput if (strlen(syms->alias)) 1063947b4ad1SIngo Molnar snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); 106474d5b588SJaswinder Singh Rajput else 1065947b4ad1SIngo Molnar strncpy(name, syms->symbol, MAX_NAME_LEN); 1066947b4ad1SIngo Molnar printf(" %-50s [%s]\n", name, 106786470930SIngo Molnar event_type_descriptors[type]); 106886470930SIngo Molnar 106986470930SIngo Molnar prev_type = type; 1070668b8788SArnaldo Carvalho de Melo ++printed; 107186470930SIngo Molnar } 107286470930SIngo Molnar 1073668b8788SArnaldo Carvalho de Melo if (ntypes_printed) { 1074668b8788SArnaldo Carvalho de Melo printed = 0; 1075689d3018SMarti Raudsepp printf("\n"); 1076668b8788SArnaldo Carvalho de Melo } 1077668b8788SArnaldo Carvalho de Melo print_hwcache_events(event_glob); 107873c24cb8SJaswinder Singh Rajput 1079668b8788SArnaldo Carvalho de Melo if (event_glob != NULL) 1080668b8788SArnaldo Carvalho de Melo return; 108173c24cb8SJaswinder Singh Rajput 1082689d3018SMarti Raudsepp printf("\n"); 1083947b4ad1SIngo Molnar printf(" %-50s [%s]\n", 10841cf4a063SArnaldo Carvalho de Melo "rNNN (see 'perf list --help' on how to encode it)", 10851cf4a063SArnaldo Carvalho de Melo event_type_descriptors[PERF_TYPE_RAW]); 1086689d3018SMarti Raudsepp printf("\n"); 108786470930SIngo Molnar 1088947b4ad1SIngo Molnar printf(" %-50s [%s]\n", 108941bdcb23SLiming Wang "mem:<addr>[:access]", 109041bdcb23SLiming Wang event_type_descriptors[PERF_TYPE_BREAKPOINT]); 10911b290d67SFrederic Weisbecker printf("\n"); 10921b290d67SFrederic Weisbecker 1093668b8788SArnaldo Carvalho de Melo print_tracepoint_events(NULL, NULL); 1094f6bdafefSJason Baron 109586470930SIngo Molnar exit(129); 109686470930SIngo Molnar } 1097