1d2709c7cSDavid Howells #include <linux/hw_breakpoint.h> 28dd2a131SJiri Olsa #include <linux/err.h> 386470930SIngo Molnar #include "util.h" 46b58e7f1SUlrich Drepper #include "../perf.h" 5361c99a6SArnaldo Carvalho de Melo #include "evlist.h" 669aad6f1SArnaldo Carvalho de Melo #include "evsel.h" 786470930SIngo Molnar #include "parse-options.h" 886470930SIngo Molnar #include "parse-events.h" 986470930SIngo Molnar #include "exec_cmd.h" 1042f60c2dSKan Liang #include "string.h" 115aab621bSArnaldo Carvalho de Melo #include "symbol.h" 125beeded1SJason Baron #include "cache.h" 138755a8f2SArjan van de Ven #include "header.h" 146e81c74cSMasami Hiramatsu #include "debug.h" 15592d5a6bSJiri Olsa #include <api/fs/tracing_path.h> 16ac20de6fSZheng Yan #include "parse-events-bison.h" 1790e2b22dSJiri Olsa #define YY_EXTRA_TYPE int 1889812fc8SJiri Olsa #include "parse-events-flex.h" 195f537a26SJiri Olsa #include "pmu.h" 20b41f1cecSNamhyung Kim #include "thread_map.h" 21f30a79b0SJiri Olsa #include "cpumap.h" 22b39b8393SJiri Olsa #include "asm/bug.h" 2389812fc8SJiri Olsa 2489812fc8SJiri Olsa #define MAX_NAME_LEN 100 2586470930SIngo Molnar 2682ba1f2fSJiri Olsa #ifdef PARSER_DEBUG 2782ba1f2fSJiri Olsa extern int parse_events_debug; 2882ba1f2fSJiri Olsa #endif 29ac20de6fSZheng Yan int parse_events_parse(void *data, void *scanner); 30e637d177SHe Kuang static int get_config_terms(struct list_head *head_config, 31e637d177SHe Kuang struct list_head *head_terms __maybe_unused); 32bcd3279fSFrederic Weisbecker 33dcb4e102SKan Liang static struct perf_pmu_event_symbol *perf_pmu_events_list; 34dcb4e102SKan Liang /* 35dcb4e102SKan Liang * The variable indicates the number of supported pmu event symbols. 36dcb4e102SKan Liang * 0 means not initialized and ready to init 37dcb4e102SKan Liang * -1 means failed to init, don't try anymore 38dcb4e102SKan Liang * >0 is the number of supported pmu event symbols 39dcb4e102SKan Liang */ 40dcb4e102SKan Liang static int perf_pmu_events_list_num; 41dcb4e102SKan Liang 42705750f2SYunlong Song struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = { 431dc12760SJiri Olsa [PERF_COUNT_HW_CPU_CYCLES] = { 441dc12760SJiri Olsa .symbol = "cpu-cycles", 451dc12760SJiri Olsa .alias = "cycles", 461dc12760SJiri Olsa }, 471dc12760SJiri Olsa [PERF_COUNT_HW_INSTRUCTIONS] = { 481dc12760SJiri Olsa .symbol = "instructions", 491dc12760SJiri Olsa .alias = "", 501dc12760SJiri Olsa }, 511dc12760SJiri Olsa [PERF_COUNT_HW_CACHE_REFERENCES] = { 521dc12760SJiri Olsa .symbol = "cache-references", 531dc12760SJiri Olsa .alias = "", 541dc12760SJiri Olsa }, 551dc12760SJiri Olsa [PERF_COUNT_HW_CACHE_MISSES] = { 561dc12760SJiri Olsa .symbol = "cache-misses", 571dc12760SJiri Olsa .alias = "", 581dc12760SJiri Olsa }, 591dc12760SJiri Olsa [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 601dc12760SJiri Olsa .symbol = "branch-instructions", 611dc12760SJiri Olsa .alias = "branches", 621dc12760SJiri Olsa }, 631dc12760SJiri Olsa [PERF_COUNT_HW_BRANCH_MISSES] = { 641dc12760SJiri Olsa .symbol = "branch-misses", 651dc12760SJiri Olsa .alias = "", 661dc12760SJiri Olsa }, 671dc12760SJiri Olsa [PERF_COUNT_HW_BUS_CYCLES] = { 681dc12760SJiri Olsa .symbol = "bus-cycles", 691dc12760SJiri Olsa .alias = "", 701dc12760SJiri Olsa }, 711dc12760SJiri Olsa [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = { 721dc12760SJiri Olsa .symbol = "stalled-cycles-frontend", 731dc12760SJiri Olsa .alias = "idle-cycles-frontend", 741dc12760SJiri Olsa }, 751dc12760SJiri Olsa [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = { 761dc12760SJiri Olsa .symbol = "stalled-cycles-backend", 771dc12760SJiri Olsa .alias = "idle-cycles-backend", 781dc12760SJiri Olsa }, 791dc12760SJiri Olsa [PERF_COUNT_HW_REF_CPU_CYCLES] = { 801dc12760SJiri Olsa .symbol = "ref-cycles", 811dc12760SJiri Olsa .alias = "", 821dc12760SJiri Olsa }, 831dc12760SJiri Olsa }; 8486470930SIngo Molnar 85705750f2SYunlong Song struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = { 861dc12760SJiri Olsa [PERF_COUNT_SW_CPU_CLOCK] = { 871dc12760SJiri Olsa .symbol = "cpu-clock", 881dc12760SJiri Olsa .alias = "", 891dc12760SJiri Olsa }, 901dc12760SJiri Olsa [PERF_COUNT_SW_TASK_CLOCK] = { 911dc12760SJiri Olsa .symbol = "task-clock", 921dc12760SJiri Olsa .alias = "", 931dc12760SJiri Olsa }, 941dc12760SJiri Olsa [PERF_COUNT_SW_PAGE_FAULTS] = { 951dc12760SJiri Olsa .symbol = "page-faults", 961dc12760SJiri Olsa .alias = "faults", 971dc12760SJiri Olsa }, 981dc12760SJiri Olsa [PERF_COUNT_SW_CONTEXT_SWITCHES] = { 991dc12760SJiri Olsa .symbol = "context-switches", 1001dc12760SJiri Olsa .alias = "cs", 1011dc12760SJiri Olsa }, 1021dc12760SJiri Olsa [PERF_COUNT_SW_CPU_MIGRATIONS] = { 1031dc12760SJiri Olsa .symbol = "cpu-migrations", 1041dc12760SJiri Olsa .alias = "migrations", 1051dc12760SJiri Olsa }, 1061dc12760SJiri Olsa [PERF_COUNT_SW_PAGE_FAULTS_MIN] = { 1071dc12760SJiri Olsa .symbol = "minor-faults", 1081dc12760SJiri Olsa .alias = "", 1091dc12760SJiri Olsa }, 1101dc12760SJiri Olsa [PERF_COUNT_SW_PAGE_FAULTS_MAJ] = { 1111dc12760SJiri Olsa .symbol = "major-faults", 1121dc12760SJiri Olsa .alias = "", 1131dc12760SJiri Olsa }, 1141dc12760SJiri Olsa [PERF_COUNT_SW_ALIGNMENT_FAULTS] = { 1151dc12760SJiri Olsa .symbol = "alignment-faults", 1161dc12760SJiri Olsa .alias = "", 1171dc12760SJiri Olsa }, 1181dc12760SJiri Olsa [PERF_COUNT_SW_EMULATION_FAULTS] = { 1191dc12760SJiri Olsa .symbol = "emulation-faults", 1201dc12760SJiri Olsa .alias = "", 1211dc12760SJiri Olsa }, 122d22d1a2aSAdrian Hunter [PERF_COUNT_SW_DUMMY] = { 123d22d1a2aSAdrian Hunter .symbol = "dummy", 124d22d1a2aSAdrian Hunter .alias = "", 125d22d1a2aSAdrian Hunter }, 12686470930SIngo Molnar }; 12786470930SIngo Molnar 128cdd6c482SIngo Molnar #define __PERF_EVENT_FIELD(config, name) \ 129cdd6c482SIngo Molnar ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT) 13086470930SIngo Molnar 131cdd6c482SIngo Molnar #define PERF_EVENT_RAW(config) __PERF_EVENT_FIELD(config, RAW) 132cdd6c482SIngo Molnar #define PERF_EVENT_CONFIG(config) __PERF_EVENT_FIELD(config, CONFIG) 133cdd6c482SIngo Molnar #define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE) 134cdd6c482SIngo Molnar #define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT) 13586470930SIngo Molnar 1366b58e7f1SUlrich Drepper #define for_each_subsystem(sys_dir, sys_dirent, sys_next) \ 137f6bdafefSJason Baron while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ 1386b58e7f1SUlrich Drepper if (sys_dirent.d_type == DT_DIR && \ 139f6bdafefSJason Baron (strcmp(sys_dirent.d_name, ".")) && \ 140f6bdafefSJason Baron (strcmp(sys_dirent.d_name, ".."))) 141f6bdafefSJason Baron 142ae07b63fSPeter Zijlstra static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir) 143ae07b63fSPeter Zijlstra { 144ae07b63fSPeter Zijlstra char evt_path[MAXPATHLEN]; 145ae07b63fSPeter Zijlstra int fd; 146ae07b63fSPeter Zijlstra 147ebf294bfSArnaldo Carvalho de Melo snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path, 148ae07b63fSPeter Zijlstra sys_dir->d_name, evt_dir->d_name); 149ae07b63fSPeter Zijlstra fd = open(evt_path, O_RDONLY); 150ae07b63fSPeter Zijlstra if (fd < 0) 151ae07b63fSPeter Zijlstra return -EINVAL; 152ae07b63fSPeter Zijlstra close(fd); 153ae07b63fSPeter Zijlstra 154ae07b63fSPeter Zijlstra return 0; 155ae07b63fSPeter Zijlstra } 156ae07b63fSPeter Zijlstra 1576b58e7f1SUlrich Drepper #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) \ 158f6bdafefSJason Baron while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \ 1596b58e7f1SUlrich Drepper if (evt_dirent.d_type == DT_DIR && \ 160f6bdafefSJason Baron (strcmp(evt_dirent.d_name, ".")) && \ 161ae07b63fSPeter Zijlstra (strcmp(evt_dirent.d_name, "..")) && \ 162ae07b63fSPeter Zijlstra (!tp_event_has_id(&sys_dirent, &evt_dirent))) 163f6bdafefSJason Baron 164270bbbe8SLi Zefan #define MAX_EVENT_LENGTH 512 165f6bdafefSJason Baron 166f6bdafefSJason Baron 1671ef2ed10SFrederic Weisbecker struct tracepoint_path *tracepoint_id_to_path(u64 config) 168f6bdafefSJason Baron { 1691ef2ed10SFrederic Weisbecker struct tracepoint_path *path = NULL; 170f6bdafefSJason Baron DIR *sys_dir, *evt_dir; 171f6bdafefSJason Baron struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 1728aa8a7c8SStephane Eranian char id_buf[24]; 173725b1368SEric Dumazet int fd; 174f6bdafefSJason Baron u64 id; 175f6bdafefSJason Baron char evt_path[MAXPATHLEN]; 176725b1368SEric Dumazet char dir_path[MAXPATHLEN]; 177f6bdafefSJason Baron 178ebf294bfSArnaldo Carvalho de Melo sys_dir = opendir(tracing_events_path); 179f6bdafefSJason Baron if (!sys_dir) 180725b1368SEric Dumazet return NULL; 181f6bdafefSJason Baron 1826b58e7f1SUlrich Drepper for_each_subsystem(sys_dir, sys_dirent, sys_next) { 183725b1368SEric Dumazet 184ebf294bfSArnaldo Carvalho de Melo snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path, 185725b1368SEric Dumazet sys_dirent.d_name); 186725b1368SEric Dumazet evt_dir = opendir(dir_path); 187725b1368SEric Dumazet if (!evt_dir) 1886b58e7f1SUlrich Drepper continue; 189725b1368SEric Dumazet 1906b58e7f1SUlrich Drepper for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 191725b1368SEric Dumazet 192725b1368SEric Dumazet snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, 193f6bdafefSJason Baron evt_dirent.d_name); 194725b1368SEric Dumazet fd = open(evt_path, O_RDONLY); 195f6bdafefSJason Baron if (fd < 0) 196f6bdafefSJason Baron continue; 197f6bdafefSJason Baron if (read(fd, id_buf, sizeof(id_buf)) < 0) { 198f6bdafefSJason Baron close(fd); 199f6bdafefSJason Baron continue; 200f6bdafefSJason Baron } 201f6bdafefSJason Baron close(fd); 202f6bdafefSJason Baron id = atoll(id_buf); 203f6bdafefSJason Baron if (id == config) { 204f6bdafefSJason Baron closedir(evt_dir); 205f6bdafefSJason Baron closedir(sys_dir); 20659b4caebSJulia Lawall path = zalloc(sizeof(*path)); 2071ef2ed10SFrederic Weisbecker path->system = malloc(MAX_EVENT_LENGTH); 2081ef2ed10SFrederic Weisbecker if (!path->system) { 2091ef2ed10SFrederic Weisbecker free(path); 2101ef2ed10SFrederic Weisbecker return NULL; 2111ef2ed10SFrederic Weisbecker } 2121ef2ed10SFrederic Weisbecker path->name = malloc(MAX_EVENT_LENGTH); 2131ef2ed10SFrederic Weisbecker if (!path->name) { 21474cf249dSArnaldo Carvalho de Melo zfree(&path->system); 2151ef2ed10SFrederic Weisbecker free(path); 2161ef2ed10SFrederic Weisbecker return NULL; 2171ef2ed10SFrederic Weisbecker } 2181ef2ed10SFrederic Weisbecker strncpy(path->system, sys_dirent.d_name, 2191ef2ed10SFrederic Weisbecker MAX_EVENT_LENGTH); 2201ef2ed10SFrederic Weisbecker strncpy(path->name, evt_dirent.d_name, 2211ef2ed10SFrederic Weisbecker MAX_EVENT_LENGTH); 2221ef2ed10SFrederic Weisbecker return path; 223f6bdafefSJason Baron } 224f6bdafefSJason Baron } 225f6bdafefSJason Baron closedir(evt_dir); 226f6bdafefSJason Baron } 227f6bdafefSJason Baron 228f6bdafefSJason Baron closedir(sys_dir); 2291ef2ed10SFrederic Weisbecker return NULL; 2301ef2ed10SFrederic Weisbecker } 2311ef2ed10SFrederic Weisbecker 232e7c93f09SNamhyung Kim struct tracepoint_path *tracepoint_name_to_path(const char *name) 233e7c93f09SNamhyung Kim { 234e7c93f09SNamhyung Kim struct tracepoint_path *path = zalloc(sizeof(*path)); 235e7c93f09SNamhyung Kim char *str = strchr(name, ':'); 236e7c93f09SNamhyung Kim 237e7c93f09SNamhyung Kim if (path == NULL || str == NULL) { 238e7c93f09SNamhyung Kim free(path); 239e7c93f09SNamhyung Kim return NULL; 240e7c93f09SNamhyung Kim } 241e7c93f09SNamhyung Kim 242e7c93f09SNamhyung Kim path->system = strndup(name, str - name); 243e7c93f09SNamhyung Kim path->name = strdup(str+1); 244e7c93f09SNamhyung Kim 245e7c93f09SNamhyung Kim if (path->system == NULL || path->name == NULL) { 24674cf249dSArnaldo Carvalho de Melo zfree(&path->system); 24774cf249dSArnaldo Carvalho de Melo zfree(&path->name); 248e7c93f09SNamhyung Kim free(path); 249e7c93f09SNamhyung Kim path = NULL; 250e7c93f09SNamhyung Kim } 251e7c93f09SNamhyung Kim 252e7c93f09SNamhyung Kim return path; 253e7c93f09SNamhyung Kim } 254e7c93f09SNamhyung Kim 2551424dc96SDavid Ahern const char *event_type(int type) 2561424dc96SDavid Ahern { 2571424dc96SDavid Ahern switch (type) { 2581424dc96SDavid Ahern case PERF_TYPE_HARDWARE: 2591424dc96SDavid Ahern return "hardware"; 2601424dc96SDavid Ahern 2611424dc96SDavid Ahern case PERF_TYPE_SOFTWARE: 2621424dc96SDavid Ahern return "software"; 2631424dc96SDavid Ahern 2641424dc96SDavid Ahern case PERF_TYPE_TRACEPOINT: 2651424dc96SDavid Ahern return "tracepoint"; 2661424dc96SDavid Ahern 2671424dc96SDavid Ahern case PERF_TYPE_HW_CACHE: 2681424dc96SDavid Ahern return "hardware-cache"; 2691424dc96SDavid Ahern 2701424dc96SDavid Ahern default: 2711424dc96SDavid Ahern break; 2721424dc96SDavid Ahern } 2731424dc96SDavid Ahern 2741424dc96SDavid Ahern return "unknown"; 2751424dc96SDavid Ahern } 2761424dc96SDavid Ahern 2777ae92e74SYan, Zheng 2787ae92e74SYan, Zheng 279410136f5SStephane Eranian static struct perf_evsel * 280410136f5SStephane Eranian __add_event(struct list_head *list, int *idx, 2817ae92e74SYan, Zheng struct perf_event_attr *attr, 282930a2e29SJiri Olsa char *name, struct cpu_map *cpus, 283930a2e29SJiri Olsa struct list_head *config_terms) 28489812fc8SJiri Olsa { 28589812fc8SJiri Olsa struct perf_evsel *evsel; 28689812fc8SJiri Olsa 28789812fc8SJiri Olsa event_attr_init(attr); 28889812fc8SJiri Olsa 289ef503831SArnaldo Carvalho de Melo evsel = perf_evsel__new_idx(attr, (*idx)++); 290c5cd8ac0SDavid Ahern if (!evsel) 291410136f5SStephane Eranian return NULL; 29289812fc8SJiri Olsa 293f30a79b0SJiri Olsa evsel->cpus = cpu_map__get(cpus); 294fce4d296SAdrian Hunter evsel->own_cpus = cpu_map__get(cpus); 295f30a79b0SJiri Olsa 2969db1763cSArnaldo Carvalho de Melo if (name) 29789812fc8SJiri Olsa evsel->name = strdup(name); 298930a2e29SJiri Olsa 299930a2e29SJiri Olsa if (config_terms) 300930a2e29SJiri Olsa list_splice(config_terms, &evsel->config_terms); 301930a2e29SJiri Olsa 302b847cbdcSJiri Olsa list_add_tail(&evsel->node, list); 303410136f5SStephane Eranian return evsel; 30489812fc8SJiri Olsa } 30589812fc8SJiri Olsa 306c5cd8ac0SDavid Ahern static int add_event(struct list_head *list, int *idx, 307930a2e29SJiri Olsa struct perf_event_attr *attr, char *name, 308930a2e29SJiri Olsa struct list_head *config_terms) 3097ae92e74SYan, Zheng { 310930a2e29SJiri Olsa return __add_event(list, idx, attr, name, NULL, config_terms) ? 0 : -ENOMEM; 3117ae92e74SYan, Zheng } 3127ae92e74SYan, Zheng 3130b668bc9SArnaldo Carvalho de Melo static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) 31486470930SIngo Molnar { 31586470930SIngo Molnar int i, j; 31661c45981SPaul Mackerras int n, longest = -1; 31786470930SIngo Molnar 31886470930SIngo Molnar for (i = 0; i < size; i++) { 3190b668bc9SArnaldo Carvalho de Melo for (j = 0; j < PERF_EVSEL__MAX_ALIASES && names[i][j]; j++) { 32061c45981SPaul Mackerras n = strlen(names[i][j]); 32189812fc8SJiri Olsa if (n > longest && !strncasecmp(str, names[i][j], n)) 32261c45981SPaul Mackerras longest = n; 32361c45981SPaul Mackerras } 32489812fc8SJiri Olsa if (longest > 0) 32586470930SIngo Molnar return i; 32686470930SIngo Molnar } 32786470930SIngo Molnar 3288953645fSIngo Molnar return -1; 32986470930SIngo Molnar } 33086470930SIngo Molnar 331c5cd8ac0SDavid Ahern int parse_events_add_cache(struct list_head *list, int *idx, 33289812fc8SJiri Olsa char *type, char *op_result1, char *op_result2) 33386470930SIngo Molnar { 33489812fc8SJiri Olsa struct perf_event_attr attr; 33589812fc8SJiri Olsa char name[MAX_NAME_LEN]; 33661c45981SPaul Mackerras int cache_type = -1, cache_op = -1, cache_result = -1; 33789812fc8SJiri Olsa char *op_result[2] = { op_result1, op_result2 }; 33889812fc8SJiri Olsa int i, n; 33986470930SIngo Molnar 34086470930SIngo Molnar /* 34186470930SIngo Molnar * No fallback - if we cannot get a clear cache type 34286470930SIngo Molnar * then bail out: 34386470930SIngo Molnar */ 3440b668bc9SArnaldo Carvalho de Melo cache_type = parse_aliases(type, perf_evsel__hw_cache, 34589812fc8SJiri Olsa PERF_COUNT_HW_CACHE_MAX); 34686470930SIngo Molnar if (cache_type == -1) 34789812fc8SJiri Olsa return -EINVAL; 34886470930SIngo Molnar 34989812fc8SJiri Olsa n = snprintf(name, MAX_NAME_LEN, "%s", type); 35089812fc8SJiri Olsa 35189812fc8SJiri Olsa for (i = 0; (i < 2) && (op_result[i]); i++) { 35289812fc8SJiri Olsa char *str = op_result[i]; 35389812fc8SJiri Olsa 354275ef387SJiri Olsa n += snprintf(name + n, MAX_NAME_LEN - n, "-%s", str); 35561c45981SPaul Mackerras 35661c45981SPaul Mackerras if (cache_op == -1) { 3570b668bc9SArnaldo Carvalho de Melo cache_op = parse_aliases(str, perf_evsel__hw_cache_op, 35861c45981SPaul Mackerras PERF_COUNT_HW_CACHE_OP_MAX); 35961c45981SPaul Mackerras if (cache_op >= 0) { 3600b668bc9SArnaldo Carvalho de Melo if (!perf_evsel__is_cache_op_valid(cache_type, cache_op)) 36189812fc8SJiri Olsa return -EINVAL; 36261c45981SPaul Mackerras continue; 36361c45981SPaul Mackerras } 36461c45981SPaul Mackerras } 36561c45981SPaul Mackerras 36661c45981SPaul Mackerras if (cache_result == -1) { 3670b668bc9SArnaldo Carvalho de Melo cache_result = parse_aliases(str, perf_evsel__hw_cache_result, 36861c45981SPaul Mackerras PERF_COUNT_HW_CACHE_RESULT_MAX); 36961c45981SPaul Mackerras if (cache_result >= 0) 37061c45981SPaul Mackerras continue; 37161c45981SPaul Mackerras } 37261c45981SPaul Mackerras } 37361c45981SPaul Mackerras 37486470930SIngo Molnar /* 37586470930SIngo Molnar * Fall back to reads: 37686470930SIngo Molnar */ 3778953645fSIngo Molnar if (cache_op == -1) 3788953645fSIngo Molnar cache_op = PERF_COUNT_HW_CACHE_OP_READ; 37986470930SIngo Molnar 38086470930SIngo Molnar /* 38186470930SIngo Molnar * Fall back to accesses: 38286470930SIngo Molnar */ 38386470930SIngo Molnar if (cache_result == -1) 38486470930SIngo Molnar cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS; 38586470930SIngo Molnar 38689812fc8SJiri Olsa memset(&attr, 0, sizeof(attr)); 38789812fc8SJiri Olsa attr.config = cache_type | (cache_op << 8) | (cache_result << 16); 38889812fc8SJiri Olsa attr.type = PERF_TYPE_HW_CACHE; 389930a2e29SJiri Olsa return add_event(list, idx, &attr, name, NULL); 39086470930SIngo Molnar } 39186470930SIngo Molnar 392272ed29aSJiri Olsa static void tracepoint_error(struct parse_events_error *e, int err, 39319658171SJiri Olsa char *sys, char *name) 39419658171SJiri Olsa { 39519658171SJiri Olsa char help[BUFSIZ]; 39619658171SJiri Olsa 39719658171SJiri Olsa /* 39819658171SJiri Olsa * We get error directly from syscall errno ( > 0), 39919658171SJiri Olsa * or from encoded pointer's error ( < 0). 40019658171SJiri Olsa */ 40119658171SJiri Olsa err = abs(err); 40219658171SJiri Olsa 40319658171SJiri Olsa switch (err) { 40419658171SJiri Olsa case EACCES: 405272ed29aSJiri Olsa e->str = strdup("can't access trace events"); 40619658171SJiri Olsa break; 40719658171SJiri Olsa case ENOENT: 408272ed29aSJiri Olsa e->str = strdup("unknown tracepoint"); 40919658171SJiri Olsa break; 41019658171SJiri Olsa default: 411272ed29aSJiri Olsa e->str = strdup("failed to add tracepoint"); 41219658171SJiri Olsa break; 41319658171SJiri Olsa } 41419658171SJiri Olsa 41519658171SJiri Olsa tracing_path__strerror_open_tp(err, help, sizeof(help), sys, name); 416272ed29aSJiri Olsa e->help = strdup(help); 41719658171SJiri Olsa } 41819658171SJiri Olsa 419c5cd8ac0SDavid Ahern static int add_tracepoint(struct list_head *list, int *idx, 420e2f9f8eaSJiri Olsa char *sys_name, char *evt_name, 421272ed29aSJiri Olsa struct parse_events_error *err, 422e637d177SHe Kuang struct list_head *head_config) 423bcd3279fSFrederic Weisbecker { 42482fe1c29SArnaldo Carvalho de Melo struct perf_evsel *evsel; 425bcd3279fSFrederic Weisbecker 426ef503831SArnaldo Carvalho de Melo evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++); 42719658171SJiri Olsa if (IS_ERR(evsel)) { 428272ed29aSJiri Olsa tracepoint_error(err, PTR_ERR(evsel), sys_name, evt_name); 4298dd2a131SJiri Olsa return PTR_ERR(evsel); 43019658171SJiri Olsa } 431bcd3279fSFrederic Weisbecker 432e637d177SHe Kuang if (head_config) { 433e637d177SHe Kuang LIST_HEAD(config_terms); 434e637d177SHe Kuang 435e637d177SHe Kuang if (get_config_terms(head_config, &config_terms)) 436e637d177SHe Kuang return -ENOMEM; 437e637d177SHe Kuang list_splice(&config_terms, &evsel->config_terms); 438e637d177SHe Kuang } 439e637d177SHe Kuang 44082fe1c29SArnaldo Carvalho de Melo list_add_tail(&evsel->node, list); 44182fe1c29SArnaldo Carvalho de Melo return 0; 442bcd3279fSFrederic Weisbecker } 443bcd3279fSFrederic Weisbecker 444c5cd8ac0SDavid Ahern static int add_tracepoint_multi_event(struct list_head *list, int *idx, 445e2f9f8eaSJiri Olsa char *sys_name, char *evt_name, 446272ed29aSJiri Olsa struct parse_events_error *err, 447e637d177SHe Kuang struct list_head *head_config) 448bcd3279fSFrederic Weisbecker { 449bcd3279fSFrederic Weisbecker char evt_path[MAXPATHLEN]; 450bcd3279fSFrederic Weisbecker struct dirent *evt_ent; 451bcd3279fSFrederic Weisbecker DIR *evt_dir; 45289812fc8SJiri Olsa int ret = 0; 453bcd3279fSFrederic Weisbecker 454ebf294bfSArnaldo Carvalho de Melo snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name); 455bcd3279fSFrederic Weisbecker evt_dir = opendir(evt_path); 456bcd3279fSFrederic Weisbecker if (!evt_dir) { 457272ed29aSJiri Olsa tracepoint_error(err, errno, sys_name, evt_name); 45889812fc8SJiri Olsa return -1; 459bcd3279fSFrederic Weisbecker } 460bcd3279fSFrederic Weisbecker 46189812fc8SJiri Olsa while (!ret && (evt_ent = readdir(evt_dir))) { 462bcd3279fSFrederic Weisbecker if (!strcmp(evt_ent->d_name, ".") 463bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "..") 464bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "enable") 465bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "filter")) 466bcd3279fSFrederic Weisbecker continue; 467bcd3279fSFrederic Weisbecker 46889812fc8SJiri Olsa if (!strglobmatch(evt_ent->d_name, evt_name)) 469fb1d2edfSMasami Hiramatsu continue; 470fb1d2edfSMasami Hiramatsu 471e637d177SHe Kuang ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name, 472272ed29aSJiri Olsa err, head_config); 473bcd3279fSFrederic Weisbecker } 474bcd3279fSFrederic Weisbecker 4750bd3f084SJiri Olsa closedir(evt_dir); 47689812fc8SJiri Olsa return ret; 477bcd3279fSFrederic Weisbecker } 478bcd3279fSFrederic Weisbecker 479c5cd8ac0SDavid Ahern static int add_tracepoint_event(struct list_head *list, int *idx, 480e2f9f8eaSJiri Olsa char *sys_name, char *evt_name, 481272ed29aSJiri Olsa struct parse_events_error *err, 482e637d177SHe Kuang struct list_head *head_config) 483f35488f9SJiri Olsa { 484f35488f9SJiri Olsa return strpbrk(evt_name, "*?") ? 485e637d177SHe Kuang add_tracepoint_multi_event(list, idx, sys_name, evt_name, 486272ed29aSJiri Olsa err, head_config) : 487e637d177SHe Kuang add_tracepoint(list, idx, sys_name, evt_name, 488272ed29aSJiri Olsa err, head_config); 489f35488f9SJiri Olsa } 490f35488f9SJiri Olsa 491c5cd8ac0SDavid Ahern static int add_tracepoint_multi_sys(struct list_head *list, int *idx, 492e2f9f8eaSJiri Olsa char *sys_name, char *evt_name, 493272ed29aSJiri Olsa struct parse_events_error *err, 494e637d177SHe Kuang struct list_head *head_config) 495f35488f9SJiri Olsa { 496f35488f9SJiri Olsa struct dirent *events_ent; 497f35488f9SJiri Olsa DIR *events_dir; 498f35488f9SJiri Olsa int ret = 0; 499f35488f9SJiri Olsa 500f35488f9SJiri Olsa events_dir = opendir(tracing_events_path); 501f35488f9SJiri Olsa if (!events_dir) { 502272ed29aSJiri Olsa tracepoint_error(err, errno, sys_name, evt_name); 503f35488f9SJiri Olsa return -1; 504f35488f9SJiri Olsa } 505f35488f9SJiri Olsa 506f35488f9SJiri Olsa while (!ret && (events_ent = readdir(events_dir))) { 507f35488f9SJiri Olsa if (!strcmp(events_ent->d_name, ".") 508f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "..") 509f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "enable") 510f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "header_event") 511f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "header_page")) 512f35488f9SJiri Olsa continue; 513f35488f9SJiri Olsa 514f35488f9SJiri Olsa if (!strglobmatch(events_ent->d_name, sys_name)) 515f35488f9SJiri Olsa continue; 516f35488f9SJiri Olsa 517f35488f9SJiri Olsa ret = add_tracepoint_event(list, idx, events_ent->d_name, 518272ed29aSJiri Olsa evt_name, err, head_config); 519f35488f9SJiri Olsa } 520f35488f9SJiri Olsa 521f35488f9SJiri Olsa closedir(events_dir); 522f35488f9SJiri Olsa return ret; 523f35488f9SJiri Olsa } 524f35488f9SJiri Olsa 52589812fc8SJiri Olsa static int 52689812fc8SJiri Olsa parse_breakpoint_type(const char *type, struct perf_event_attr *attr) 5271b290d67SFrederic Weisbecker { 5281b290d67SFrederic Weisbecker int i; 5291b290d67SFrederic Weisbecker 5301b290d67SFrederic Weisbecker for (i = 0; i < 3; i++) { 53189812fc8SJiri Olsa if (!type || !type[i]) 5321b290d67SFrederic Weisbecker break; 5331b290d67SFrederic Weisbecker 5347582732fSJiri Olsa #define CHECK_SET_TYPE(bit) \ 5357582732fSJiri Olsa do { \ 5367582732fSJiri Olsa if (attr->bp_type & bit) \ 5377582732fSJiri Olsa return -EINVAL; \ 5387582732fSJiri Olsa else \ 5397582732fSJiri Olsa attr->bp_type |= bit; \ 5407582732fSJiri Olsa } while (0) 5417582732fSJiri Olsa 5421b290d67SFrederic Weisbecker switch (type[i]) { 5431b290d67SFrederic Weisbecker case 'r': 5447582732fSJiri Olsa CHECK_SET_TYPE(HW_BREAKPOINT_R); 5451b290d67SFrederic Weisbecker break; 5461b290d67SFrederic Weisbecker case 'w': 5477582732fSJiri Olsa CHECK_SET_TYPE(HW_BREAKPOINT_W); 5481b290d67SFrederic Weisbecker break; 5491b290d67SFrederic Weisbecker case 'x': 5507582732fSJiri Olsa CHECK_SET_TYPE(HW_BREAKPOINT_X); 5511b290d67SFrederic Weisbecker break; 5521b290d67SFrederic Weisbecker default: 55389812fc8SJiri Olsa return -EINVAL; 5541b290d67SFrederic Weisbecker } 5551b290d67SFrederic Weisbecker } 55689812fc8SJiri Olsa 5577582732fSJiri Olsa #undef CHECK_SET_TYPE 5587582732fSJiri Olsa 5591b290d67SFrederic Weisbecker if (!attr->bp_type) /* Default */ 5601b290d67SFrederic Weisbecker attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; 5611b290d67SFrederic Weisbecker 56289812fc8SJiri Olsa return 0; 5631b290d67SFrederic Weisbecker } 5641b290d67SFrederic Weisbecker 565c5cd8ac0SDavid Ahern int parse_events_add_breakpoint(struct list_head *list, int *idx, 5663741eb9fSJacob Shin void *ptr, char *type, u64 len) 5671b290d67SFrederic Weisbecker { 56889812fc8SJiri Olsa struct perf_event_attr attr; 5691b290d67SFrederic Weisbecker 57089812fc8SJiri Olsa memset(&attr, 0, sizeof(attr)); 5719fafd98fSJiri Olsa attr.bp_addr = (unsigned long) ptr; 5721b290d67SFrederic Weisbecker 57389812fc8SJiri Olsa if (parse_breakpoint_type(type, &attr)) 57489812fc8SJiri Olsa return -EINVAL; 5751b290d67SFrederic Weisbecker 5763741eb9fSJacob Shin /* Provide some defaults if len is not specified */ 5773741eb9fSJacob Shin if (!len) { 57889812fc8SJiri Olsa if (attr.bp_type == HW_BREAKPOINT_X) 5793741eb9fSJacob Shin len = sizeof(long); 580aa59a485SFrederic Weisbecker else 5813741eb9fSJacob Shin len = HW_BREAKPOINT_LEN_4; 5823741eb9fSJacob Shin } 5833741eb9fSJacob Shin 5843741eb9fSJacob Shin attr.bp_len = len; 585aa59a485SFrederic Weisbecker 58689812fc8SJiri Olsa attr.type = PERF_TYPE_BREAKPOINT; 5874a841d65SJovi Zhang attr.sample_period = 1; 5881b290d67SFrederic Weisbecker 589930a2e29SJiri Olsa return add_event(list, idx, &attr, NULL, NULL); 5901b290d67SFrederic Weisbecker } 5911b290d67SFrederic Weisbecker 5923b0e371cSJiri Olsa static int check_type_val(struct parse_events_term *term, 5933b0e371cSJiri Olsa struct parse_events_error *err, 5943b0e371cSJiri Olsa int type) 5953b0e371cSJiri Olsa { 5963b0e371cSJiri Olsa if (type == term->type_val) 5973b0e371cSJiri Olsa return 0; 5983b0e371cSJiri Olsa 5993b0e371cSJiri Olsa if (err) { 6003b0e371cSJiri Olsa err->idx = term->err_val; 6013b0e371cSJiri Olsa if (type == PARSE_EVENTS__TERM_TYPE_NUM) 6023b0e371cSJiri Olsa err->str = strdup("expected numeric value"); 6033b0e371cSJiri Olsa else 6043b0e371cSJiri Olsa err->str = strdup("expected string value"); 6053b0e371cSJiri Olsa } 6063b0e371cSJiri Olsa return -EINVAL; 6073b0e371cSJiri Olsa } 6083b0e371cSJiri Olsa 6090b8891a8SHe Kuang typedef int config_term_func_t(struct perf_event_attr *attr, 6100b8891a8SHe Kuang struct parse_events_term *term, 6110b8891a8SHe Kuang struct parse_events_error *err); 6120b8891a8SHe Kuang 6130b8891a8SHe Kuang static int config_term_common(struct perf_event_attr *attr, 6143b0e371cSJiri Olsa struct parse_events_term *term, 6153b0e371cSJiri Olsa struct parse_events_error *err) 6168f707d84SJiri Olsa { 61716fa7e82SJiri Olsa #define CHECK_TYPE_VAL(type) \ 61816fa7e82SJiri Olsa do { \ 6193b0e371cSJiri Olsa if (check_type_val(term, err, PARSE_EVENTS__TERM_TYPE_ ## type)) \ 62016fa7e82SJiri Olsa return -EINVAL; \ 62116fa7e82SJiri Olsa } while (0) 62216fa7e82SJiri Olsa 62316fa7e82SJiri Olsa switch (term->type_term) { 6248f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_CONFIG: 62516fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 6268f707d84SJiri Olsa attr->config = term->val.num; 6278f707d84SJiri Olsa break; 6288f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_CONFIG1: 62916fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 6308f707d84SJiri Olsa attr->config1 = term->val.num; 6318f707d84SJiri Olsa break; 6328f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_CONFIG2: 63316fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 6348f707d84SJiri Olsa attr->config2 = term->val.num; 6358f707d84SJiri Olsa break; 6368f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 63716fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 6388f707d84SJiri Olsa break; 63909af2a55SNamhyung Kim case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ: 64009af2a55SNamhyung Kim CHECK_TYPE_VAL(NUM); 64109af2a55SNamhyung Kim break; 6428f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: 6438f707d84SJiri Olsa /* 6448f707d84SJiri Olsa * TODO uncomment when the field is available 6458f707d84SJiri Olsa * attr->branch_sample_type = term->val.num; 6468f707d84SJiri Olsa */ 6478f707d84SJiri Olsa break; 64832067712SKan Liang case PARSE_EVENTS__TERM_TYPE_TIME: 64932067712SKan Liang CHECK_TYPE_VAL(NUM); 65032067712SKan Liang if (term->val.num > 1) { 65132067712SKan Liang err->str = strdup("expected 0 or 1"); 65232067712SKan Liang err->idx = term->err_val; 65332067712SKan Liang return -EINVAL; 65432067712SKan Liang } 65532067712SKan Liang break; 656d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 657d457c963SKan Liang CHECK_TYPE_VAL(STR); 658d457c963SKan Liang break; 659d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 660d457c963SKan Liang CHECK_TYPE_VAL(NUM); 661d457c963SKan Liang break; 6626b5fc39bSJiri Olsa case PARSE_EVENTS__TERM_TYPE_NAME: 6636b5fc39bSJiri Olsa CHECK_TYPE_VAL(STR); 6646b5fc39bSJiri Olsa break; 6658f707d84SJiri Olsa default: 666ffeb883eSHe Kuang err->str = strdup("unknown term"); 667ffeb883eSHe Kuang err->idx = term->err_term; 668ffeb883eSHe Kuang err->help = parse_events_formats_error_string(NULL); 6698f707d84SJiri Olsa return -EINVAL; 6708f707d84SJiri Olsa } 67116fa7e82SJiri Olsa 6728f707d84SJiri Olsa return 0; 67316fa7e82SJiri Olsa #undef CHECK_TYPE_VAL 6748f707d84SJiri Olsa } 6758f707d84SJiri Olsa 6760b8891a8SHe Kuang static int config_term_pmu(struct perf_event_attr *attr, 6770b8891a8SHe Kuang struct parse_events_term *term, 6780b8891a8SHe Kuang struct parse_events_error *err) 6790b8891a8SHe Kuang { 6800b8891a8SHe Kuang if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER) 6810b8891a8SHe Kuang /* 6820b8891a8SHe Kuang * Always succeed for sysfs terms, as we dont know 6830b8891a8SHe Kuang * at this point what type they need to have. 6840b8891a8SHe Kuang */ 6850b8891a8SHe Kuang return 0; 6860b8891a8SHe Kuang else 6870b8891a8SHe Kuang return config_term_common(attr, term, err); 6880b8891a8SHe Kuang } 6890b8891a8SHe Kuang 690e637d177SHe Kuang static int config_term_tracepoint(struct perf_event_attr *attr, 691e637d177SHe Kuang struct parse_events_term *term, 692e637d177SHe Kuang struct parse_events_error *err) 693e637d177SHe Kuang { 694e637d177SHe Kuang switch (term->type_term) { 695e637d177SHe Kuang case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 696e637d177SHe Kuang case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 697e637d177SHe Kuang return config_term_common(attr, term, err); 698e637d177SHe Kuang default: 699e637d177SHe Kuang if (err) { 700e637d177SHe Kuang err->idx = term->err_term; 701e637d177SHe Kuang err->str = strdup("unknown term"); 702e637d177SHe Kuang err->help = strdup("valid terms: call-graph,stack-size\n"); 703e637d177SHe Kuang } 704e637d177SHe Kuang return -EINVAL; 705e637d177SHe Kuang } 706e637d177SHe Kuang 707e637d177SHe Kuang return 0; 708e637d177SHe Kuang } 709e637d177SHe Kuang 7108f707d84SJiri Olsa static int config_attr(struct perf_event_attr *attr, 7113b0e371cSJiri Olsa struct list_head *head, 7120b8891a8SHe Kuang struct parse_events_error *err, 7130b8891a8SHe Kuang config_term_func_t config_term) 7148f707d84SJiri Olsa { 7156cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 7168f707d84SJiri Olsa 7178f707d84SJiri Olsa list_for_each_entry(term, head, list) 7183b0e371cSJiri Olsa if (config_term(attr, term, err)) 7198f707d84SJiri Olsa return -EINVAL; 7208f707d84SJiri Olsa 7218f707d84SJiri Olsa return 0; 7228f707d84SJiri Olsa } 7238f707d84SJiri Olsa 724930a2e29SJiri Olsa static int get_config_terms(struct list_head *head_config, 725930a2e29SJiri Olsa struct list_head *head_terms __maybe_unused) 726930a2e29SJiri Olsa { 727930a2e29SJiri Olsa #define ADD_CONFIG_TERM(__type, __name, __val) \ 728930a2e29SJiri Olsa do { \ 729930a2e29SJiri Olsa struct perf_evsel_config_term *__t; \ 730930a2e29SJiri Olsa \ 731930a2e29SJiri Olsa __t = zalloc(sizeof(*__t)); \ 732930a2e29SJiri Olsa if (!__t) \ 733930a2e29SJiri Olsa return -ENOMEM; \ 734930a2e29SJiri Olsa \ 735930a2e29SJiri Olsa INIT_LIST_HEAD(&__t->list); \ 736930a2e29SJiri Olsa __t->type = PERF_EVSEL__CONFIG_TERM_ ## __type; \ 737930a2e29SJiri Olsa __t->val.__name = __val; \ 738930a2e29SJiri Olsa list_add_tail(&__t->list, head_terms); \ 739930a2e29SJiri Olsa } while (0) 740930a2e29SJiri Olsa 741930a2e29SJiri Olsa struct parse_events_term *term; 742930a2e29SJiri Olsa 743930a2e29SJiri Olsa list_for_each_entry(term, head_config, list) { 744930a2e29SJiri Olsa switch (term->type_term) { 745ee4c7588SJiri Olsa case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 746ee4c7588SJiri Olsa ADD_CONFIG_TERM(PERIOD, period, term->val.num); 74732067712SKan Liang break; 74809af2a55SNamhyung Kim case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ: 74909af2a55SNamhyung Kim ADD_CONFIG_TERM(FREQ, freq, term->val.num); 75009af2a55SNamhyung Kim break; 75132067712SKan Liang case PARSE_EVENTS__TERM_TYPE_TIME: 75232067712SKan Liang ADD_CONFIG_TERM(TIME, time, term->val.num); 75332067712SKan Liang break; 754d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 755d457c963SKan Liang ADD_CONFIG_TERM(CALLGRAPH, callgraph, term->val.str); 756d457c963SKan Liang break; 757d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 758d457c963SKan Liang ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num); 759d457c963SKan Liang break; 760930a2e29SJiri Olsa default: 761930a2e29SJiri Olsa break; 762930a2e29SJiri Olsa } 763930a2e29SJiri Olsa } 764930a2e29SJiri Olsa #undef ADD_EVSEL_CONFIG 765930a2e29SJiri Olsa return 0; 766930a2e29SJiri Olsa } 767930a2e29SJiri Olsa 768e637d177SHe Kuang int parse_events_add_tracepoint(struct list_head *list, int *idx, 769e637d177SHe Kuang char *sys, char *event, 770272ed29aSJiri Olsa struct parse_events_error *err, 771e637d177SHe Kuang struct list_head *head_config) 772e637d177SHe Kuang { 773e637d177SHe Kuang if (head_config) { 774e637d177SHe Kuang struct perf_event_attr attr; 775e637d177SHe Kuang 776272ed29aSJiri Olsa if (config_attr(&attr, head_config, err, 777e637d177SHe Kuang config_term_tracepoint)) 778e637d177SHe Kuang return -EINVAL; 779e637d177SHe Kuang } 780e637d177SHe Kuang 781e637d177SHe Kuang if (strpbrk(sys, "*?")) 782e637d177SHe Kuang return add_tracepoint_multi_sys(list, idx, sys, event, 783272ed29aSJiri Olsa err, head_config); 784e637d177SHe Kuang else 785e637d177SHe Kuang return add_tracepoint_event(list, idx, sys, event, 786272ed29aSJiri Olsa err, head_config); 787e637d177SHe Kuang } 788e637d177SHe Kuang 78987d650beSJiri Olsa int parse_events_add_numeric(struct parse_events_evlist *data, 79087d650beSJiri Olsa struct list_head *list, 791b527bab5SRobert Richter u32 type, u64 config, 7928f707d84SJiri Olsa struct list_head *head_config) 79374d5b588SJaswinder Singh Rajput { 79489812fc8SJiri Olsa struct perf_event_attr attr; 795930a2e29SJiri Olsa LIST_HEAD(config_terms); 79674d5b588SJaswinder Singh Rajput 79789812fc8SJiri Olsa memset(&attr, 0, sizeof(attr)); 79889812fc8SJiri Olsa attr.type = type; 79989812fc8SJiri Olsa attr.config = config; 8008f707d84SJiri Olsa 801930a2e29SJiri Olsa if (head_config) { 8020b8891a8SHe Kuang if (config_attr(&attr, head_config, data->error, 8030b8891a8SHe Kuang config_term_common)) 8048f707d84SJiri Olsa return -EINVAL; 8058f707d84SJiri Olsa 806930a2e29SJiri Olsa if (get_config_terms(head_config, &config_terms)) 807930a2e29SJiri Olsa return -ENOMEM; 808930a2e29SJiri Olsa } 809930a2e29SJiri Olsa 810930a2e29SJiri Olsa return add_event(list, &data->idx, &attr, NULL, &config_terms); 811b908debdSIngo Molnar } 812b908debdSIngo Molnar 8136cee6cd3SArnaldo Carvalho de Melo static int parse_events__is_name_term(struct parse_events_term *term) 8146b5fc39bSJiri Olsa { 8156b5fc39bSJiri Olsa return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME; 8166b5fc39bSJiri Olsa } 8176b5fc39bSJiri Olsa 8189db1763cSArnaldo Carvalho de Melo static char *pmu_event_name(struct list_head *head_terms) 8196b5fc39bSJiri Olsa { 8206cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 8216b5fc39bSJiri Olsa 8226b5fc39bSJiri Olsa list_for_each_entry(term, head_terms, list) 8236b5fc39bSJiri Olsa if (parse_events__is_name_term(term)) 8246b5fc39bSJiri Olsa return term->val.str; 8256b5fc39bSJiri Olsa 8269db1763cSArnaldo Carvalho de Melo return NULL; 8276b5fc39bSJiri Olsa } 8286b5fc39bSJiri Olsa 82936adec85SJiri Olsa int parse_events_add_pmu(struct parse_events_evlist *data, 83036adec85SJiri Olsa struct list_head *list, char *name, 83136adec85SJiri Olsa struct list_head *head_config) 8325f537a26SJiri Olsa { 8335f537a26SJiri Olsa struct perf_event_attr attr; 83446441bdcSMatt Fleming struct perf_pmu_info info; 8355f537a26SJiri Olsa struct perf_pmu *pmu; 836410136f5SStephane Eranian struct perf_evsel *evsel; 837930a2e29SJiri Olsa LIST_HEAD(config_terms); 8385f537a26SJiri Olsa 8395f537a26SJiri Olsa pmu = perf_pmu__find(name); 8405f537a26SJiri Olsa if (!pmu) 8415f537a26SJiri Olsa return -EINVAL; 8425f537a26SJiri Olsa 843dc0a6202SAdrian Hunter if (pmu->default_config) { 844dc0a6202SAdrian Hunter memcpy(&attr, pmu->default_config, 845dc0a6202SAdrian Hunter sizeof(struct perf_event_attr)); 846dc0a6202SAdrian Hunter } else { 8475f537a26SJiri Olsa memset(&attr, 0, sizeof(attr)); 848dc0a6202SAdrian Hunter } 8495f537a26SJiri Olsa 850ad962273SAdrian Hunter if (!head_config) { 851ad962273SAdrian Hunter attr.type = pmu->type; 852930a2e29SJiri Olsa evsel = __add_event(list, &data->idx, &attr, NULL, pmu->cpus, NULL); 853ad962273SAdrian Hunter return evsel ? 0 : -ENOMEM; 854ad962273SAdrian Hunter } 855ad962273SAdrian Hunter 85646441bdcSMatt Fleming if (perf_pmu__check_alias(pmu, head_config, &info)) 857a6146d50SZheng Yan return -EINVAL; 858a6146d50SZheng Yan 8595f537a26SJiri Olsa /* 8605f537a26SJiri Olsa * Configure hardcoded terms first, no need to check 8615f537a26SJiri Olsa * return value when called with fail == 0 ;) 8625f537a26SJiri Olsa */ 8630b8891a8SHe Kuang if (config_attr(&attr, head_config, data->error, config_term_pmu)) 864c056ba6aSJiri Olsa return -EINVAL; 8655f537a26SJiri Olsa 866930a2e29SJiri Olsa if (get_config_terms(head_config, &config_terms)) 867930a2e29SJiri Olsa return -ENOMEM; 868930a2e29SJiri Olsa 869e64b020bSJiri Olsa if (perf_pmu__config(pmu, &attr, head_config, data->error)) 8705f537a26SJiri Olsa return -EINVAL; 8715f537a26SJiri Olsa 87236adec85SJiri Olsa evsel = __add_event(list, &data->idx, &attr, 873930a2e29SJiri Olsa pmu_event_name(head_config), pmu->cpus, 874930a2e29SJiri Olsa &config_terms); 875410136f5SStephane Eranian if (evsel) { 87646441bdcSMatt Fleming evsel->unit = info.unit; 87746441bdcSMatt Fleming evsel->scale = info.scale; 878044330c1SMatt Fleming evsel->per_pkg = info.per_pkg; 8791d9e446bSJiri Olsa evsel->snapshot = info.snapshot; 880410136f5SStephane Eranian } 881410136f5SStephane Eranian 882410136f5SStephane Eranian return evsel ? 0 : -ENOMEM; 8835f537a26SJiri Olsa } 8845f537a26SJiri Olsa 8856a4bb04cSJiri Olsa int parse_events__modifier_group(struct list_head *list, 8866a4bb04cSJiri Olsa char *event_mod) 88789efb029SJiri Olsa { 8886a4bb04cSJiri Olsa return parse_events__modifier_event(list, event_mod, true); 8896a4bb04cSJiri Olsa } 8906a4bb04cSJiri Olsa 89163dab225SArnaldo Carvalho de Melo void parse_events__set_leader(char *name, struct list_head *list) 8926a4bb04cSJiri Olsa { 8936a4bb04cSJiri Olsa struct perf_evsel *leader; 8946a4bb04cSJiri Olsa 895854f7363SWang Nan if (list_empty(list)) { 896854f7363SWang Nan WARN_ONCE(true, "WARNING: failed to set leader: empty list"); 897854f7363SWang Nan return; 898854f7363SWang Nan } 899854f7363SWang Nan 90063dab225SArnaldo Carvalho de Melo __perf_evlist__set_leader(list); 90163dab225SArnaldo Carvalho de Melo leader = list_entry(list->next, struct perf_evsel, node); 9026a4bb04cSJiri Olsa leader->group_name = name ? strdup(name) : NULL; 90389efb029SJiri Olsa } 90489efb029SJiri Olsa 905c5cd8ac0SDavid Ahern /* list_event is assumed to point to malloc'ed memory */ 9065d7be90eSJiri Olsa void parse_events_update_lists(struct list_head *list_event, 9075d7be90eSJiri Olsa struct list_head *list_all) 9085d7be90eSJiri Olsa { 9095d7be90eSJiri Olsa /* 9105d7be90eSJiri Olsa * Called for single event definition. Update the 91189efb029SJiri Olsa * 'all event' list, and reinit the 'single event' 9125d7be90eSJiri Olsa * list, for next event definition. 9135d7be90eSJiri Olsa */ 9145d7be90eSJiri Olsa list_splice_tail(list_event, list_all); 915b847cbdcSJiri Olsa free(list_event); 9165d7be90eSJiri Olsa } 9175d7be90eSJiri Olsa 918f5b1135bSJiri Olsa struct event_modifier { 919f5b1135bSJiri Olsa int eu; 920f5b1135bSJiri Olsa int ek; 921f5b1135bSJiri Olsa int eh; 922f5b1135bSJiri Olsa int eH; 923f5b1135bSJiri Olsa int eG; 924a1e12da4SJiri Olsa int eI; 925f5b1135bSJiri Olsa int precise; 926f5b1135bSJiri Olsa int exclude_GH; 9273c176311SJiri Olsa int sample_read; 928e9a7c414SMichael Ellerman int pinned; 929f5b1135bSJiri Olsa }; 93061c45981SPaul Mackerras 931f5b1135bSJiri Olsa static int get_event_modifier(struct event_modifier *mod, char *str, 932f5b1135bSJiri Olsa struct perf_evsel *evsel) 933f5b1135bSJiri Olsa { 934f5b1135bSJiri Olsa int eu = evsel ? evsel->attr.exclude_user : 0; 935f5b1135bSJiri Olsa int ek = evsel ? evsel->attr.exclude_kernel : 0; 936f5b1135bSJiri Olsa int eh = evsel ? evsel->attr.exclude_hv : 0; 937f5b1135bSJiri Olsa int eH = evsel ? evsel->attr.exclude_host : 0; 938f5b1135bSJiri Olsa int eG = evsel ? evsel->attr.exclude_guest : 0; 939a1e12da4SJiri Olsa int eI = evsel ? evsel->attr.exclude_idle : 0; 940f5b1135bSJiri Olsa int precise = evsel ? evsel->attr.precise_ip : 0; 9413c176311SJiri Olsa int sample_read = 0; 942e9a7c414SMichael Ellerman int pinned = evsel ? evsel->attr.pinned : 0; 943f5b1135bSJiri Olsa 944f5b1135bSJiri Olsa int exclude = eu | ek | eh; 945f5b1135bSJiri Olsa int exclude_GH = evsel ? evsel->exclude_GH : 0; 946f5b1135bSJiri Olsa 947f5b1135bSJiri Olsa memset(mod, 0, sizeof(*mod)); 948ceb53fbfSIngo Molnar 94961c45981SPaul Mackerras while (*str) { 950ab608344SPeter Zijlstra if (*str == 'u') { 951ab608344SPeter Zijlstra if (!exclude) 952ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 95361c45981SPaul Mackerras eu = 0; 954ab608344SPeter Zijlstra } else if (*str == 'k') { 955ab608344SPeter Zijlstra if (!exclude) 956ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 95761c45981SPaul Mackerras ek = 0; 958ab608344SPeter Zijlstra } else if (*str == 'h') { 959ab608344SPeter Zijlstra if (!exclude) 960ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 96161c45981SPaul Mackerras eh = 0; 96299320cc8SJoerg Roedel } else if (*str == 'G') { 96399320cc8SJoerg Roedel if (!exclude_GH) 96499320cc8SJoerg Roedel exclude_GH = eG = eH = 1; 96599320cc8SJoerg Roedel eG = 0; 96699320cc8SJoerg Roedel } else if (*str == 'H') { 96799320cc8SJoerg Roedel if (!exclude_GH) 96899320cc8SJoerg Roedel exclude_GH = eG = eH = 1; 96999320cc8SJoerg Roedel eH = 0; 970a1e12da4SJiri Olsa } else if (*str == 'I') { 971a1e12da4SJiri Olsa eI = 1; 972ab608344SPeter Zijlstra } else if (*str == 'p') { 973ab608344SPeter Zijlstra precise++; 9741342798cSDavid Ahern /* use of precise requires exclude_guest */ 9751342798cSDavid Ahern if (!exclude_GH) 9761342798cSDavid Ahern eG = 1; 9773c176311SJiri Olsa } else if (*str == 'S') { 9783c176311SJiri Olsa sample_read = 1; 979e9a7c414SMichael Ellerman } else if (*str == 'D') { 980e9a7c414SMichael Ellerman pinned = 1; 981ab608344SPeter Zijlstra } else 98261c45981SPaul Mackerras break; 983ab608344SPeter Zijlstra 98461c45981SPaul Mackerras ++str; 98561c45981SPaul Mackerras } 98674d5b588SJaswinder Singh Rajput 98786470930SIngo Molnar /* 98889812fc8SJiri Olsa * precise ip: 98989812fc8SJiri Olsa * 99089812fc8SJiri Olsa * 0 - SAMPLE_IP can have arbitrary skid 99189812fc8SJiri Olsa * 1 - SAMPLE_IP must have constant skid 99289812fc8SJiri Olsa * 2 - SAMPLE_IP requested to have 0 skid 99389812fc8SJiri Olsa * 3 - SAMPLE_IP must have 0 skid 99489812fc8SJiri Olsa * 99589812fc8SJiri Olsa * See also PERF_RECORD_MISC_EXACT_IP 99686470930SIngo Molnar */ 99789812fc8SJiri Olsa if (precise > 3) 99889812fc8SJiri Olsa return -EINVAL; 99986470930SIngo Molnar 1000f5b1135bSJiri Olsa mod->eu = eu; 1001f5b1135bSJiri Olsa mod->ek = ek; 1002f5b1135bSJiri Olsa mod->eh = eh; 1003f5b1135bSJiri Olsa mod->eH = eH; 1004f5b1135bSJiri Olsa mod->eG = eG; 1005a1e12da4SJiri Olsa mod->eI = eI; 1006f5b1135bSJiri Olsa mod->precise = precise; 1007f5b1135bSJiri Olsa mod->exclude_GH = exclude_GH; 10083c176311SJiri Olsa mod->sample_read = sample_read; 1009e9a7c414SMichael Ellerman mod->pinned = pinned; 1010e9a7c414SMichael Ellerman 1011f5b1135bSJiri Olsa return 0; 1012f5b1135bSJiri Olsa } 1013f5b1135bSJiri Olsa 1014534123f4SJiri Olsa /* 1015534123f4SJiri Olsa * Basic modifier sanity check to validate it contains only one 1016534123f4SJiri Olsa * instance of any modifier (apart from 'p') present. 1017534123f4SJiri Olsa */ 1018534123f4SJiri Olsa static int check_modifier(char *str) 1019534123f4SJiri Olsa { 1020534123f4SJiri Olsa char *p = str; 1021534123f4SJiri Olsa 1022534123f4SJiri Olsa /* The sizeof includes 0 byte as well. */ 1023a1e12da4SJiri Olsa if (strlen(str) > (sizeof("ukhGHpppSDI") - 1)) 1024534123f4SJiri Olsa return -1; 1025534123f4SJiri Olsa 1026534123f4SJiri Olsa while (*p) { 1027534123f4SJiri Olsa if (*p != 'p' && strchr(p + 1, *p)) 1028534123f4SJiri Olsa return -1; 1029534123f4SJiri Olsa p++; 1030534123f4SJiri Olsa } 1031534123f4SJiri Olsa 1032534123f4SJiri Olsa return 0; 1033534123f4SJiri Olsa } 1034534123f4SJiri Olsa 1035f5b1135bSJiri Olsa int parse_events__modifier_event(struct list_head *list, char *str, bool add) 1036f5b1135bSJiri Olsa { 1037f5b1135bSJiri Olsa struct perf_evsel *evsel; 1038f5b1135bSJiri Olsa struct event_modifier mod; 1039f5b1135bSJiri Olsa 1040f5b1135bSJiri Olsa if (str == NULL) 1041f5b1135bSJiri Olsa return 0; 1042f5b1135bSJiri Olsa 1043534123f4SJiri Olsa if (check_modifier(str)) 1044534123f4SJiri Olsa return -EINVAL; 1045534123f4SJiri Olsa 1046f5b1135bSJiri Olsa if (!add && get_event_modifier(&mod, str, NULL)) 1047f5b1135bSJiri Olsa return -EINVAL; 1048f5b1135bSJiri Olsa 10490050f7aaSArnaldo Carvalho de Melo __evlist__for_each(list, evsel) { 1050f5b1135bSJiri Olsa if (add && get_event_modifier(&mod, str, evsel)) 1051f5b1135bSJiri Olsa return -EINVAL; 1052f5b1135bSJiri Olsa 1053f5b1135bSJiri Olsa evsel->attr.exclude_user = mod.eu; 1054f5b1135bSJiri Olsa evsel->attr.exclude_kernel = mod.ek; 1055f5b1135bSJiri Olsa evsel->attr.exclude_hv = mod.eh; 1056f5b1135bSJiri Olsa evsel->attr.precise_ip = mod.precise; 1057f5b1135bSJiri Olsa evsel->attr.exclude_host = mod.eH; 1058f5b1135bSJiri Olsa evsel->attr.exclude_guest = mod.eG; 1059a1e12da4SJiri Olsa evsel->attr.exclude_idle = mod.eI; 1060f5b1135bSJiri Olsa evsel->exclude_GH = mod.exclude_GH; 10613c176311SJiri Olsa evsel->sample_read = mod.sample_read; 1062e9a7c414SMichael Ellerman 1063e9a7c414SMichael Ellerman if (perf_evsel__is_group_leader(evsel)) 1064e9a7c414SMichael Ellerman evsel->attr.pinned = mod.pinned; 1065ceb53fbfSIngo Molnar } 106686470930SIngo Molnar 106789812fc8SJiri Olsa return 0; 106886470930SIngo Molnar } 106986470930SIngo Molnar 1070ac2ba9f3SRobert Richter int parse_events_name(struct list_head *list, char *name) 1071ac2ba9f3SRobert Richter { 1072ac2ba9f3SRobert Richter struct perf_evsel *evsel; 1073ac2ba9f3SRobert Richter 10740050f7aaSArnaldo Carvalho de Melo __evlist__for_each(list, evsel) { 1075ac2ba9f3SRobert Richter if (!evsel->name) 1076ac2ba9f3SRobert Richter evsel->name = strdup(name); 1077ac2ba9f3SRobert Richter } 1078ac2ba9f3SRobert Richter 1079ac2ba9f3SRobert Richter return 0; 1080ac2ba9f3SRobert Richter } 1081ac2ba9f3SRobert Richter 1082dcb4e102SKan Liang static int 1083dcb4e102SKan Liang comp_pmu(const void *p1, const void *p2) 1084dcb4e102SKan Liang { 1085dcb4e102SKan Liang struct perf_pmu_event_symbol *pmu1 = (struct perf_pmu_event_symbol *) p1; 1086dcb4e102SKan Liang struct perf_pmu_event_symbol *pmu2 = (struct perf_pmu_event_symbol *) p2; 1087dcb4e102SKan Liang 1088dcb4e102SKan Liang return strcmp(pmu1->symbol, pmu2->symbol); 1089dcb4e102SKan Liang } 1090dcb4e102SKan Liang 1091dcb4e102SKan Liang static void perf_pmu__parse_cleanup(void) 1092dcb4e102SKan Liang { 1093dcb4e102SKan Liang if (perf_pmu_events_list_num > 0) { 1094dcb4e102SKan Liang struct perf_pmu_event_symbol *p; 1095dcb4e102SKan Liang int i; 1096dcb4e102SKan Liang 1097dcb4e102SKan Liang for (i = 0; i < perf_pmu_events_list_num; i++) { 1098dcb4e102SKan Liang p = perf_pmu_events_list + i; 1099dcb4e102SKan Liang free(p->symbol); 1100dcb4e102SKan Liang } 1101dcb4e102SKan Liang free(perf_pmu_events_list); 1102dcb4e102SKan Liang perf_pmu_events_list = NULL; 1103dcb4e102SKan Liang perf_pmu_events_list_num = 0; 1104dcb4e102SKan Liang } 1105dcb4e102SKan Liang } 1106dcb4e102SKan Liang 1107dcb4e102SKan Liang #define SET_SYMBOL(str, stype) \ 1108dcb4e102SKan Liang do { \ 1109dcb4e102SKan Liang p->symbol = str; \ 1110dcb4e102SKan Liang if (!p->symbol) \ 1111dcb4e102SKan Liang goto err; \ 1112dcb4e102SKan Liang p->type = stype; \ 1113dcb4e102SKan Liang } while (0) 1114dcb4e102SKan Liang 1115dcb4e102SKan Liang /* 1116dcb4e102SKan Liang * Read the pmu events list from sysfs 1117dcb4e102SKan Liang * Save it into perf_pmu_events_list 1118dcb4e102SKan Liang */ 1119dcb4e102SKan Liang static void perf_pmu__parse_init(void) 1120dcb4e102SKan Liang { 1121dcb4e102SKan Liang 1122dcb4e102SKan Liang struct perf_pmu *pmu = NULL; 1123dcb4e102SKan Liang struct perf_pmu_alias *alias; 1124dcb4e102SKan Liang int len = 0; 1125dcb4e102SKan Liang 1126dcb4e102SKan Liang pmu = perf_pmu__find("cpu"); 1127dcb4e102SKan Liang if ((pmu == NULL) || list_empty(&pmu->aliases)) { 1128dcb4e102SKan Liang perf_pmu_events_list_num = -1; 1129dcb4e102SKan Liang return; 1130dcb4e102SKan Liang } 1131dcb4e102SKan Liang list_for_each_entry(alias, &pmu->aliases, list) { 1132dcb4e102SKan Liang if (strchr(alias->name, '-')) 1133dcb4e102SKan Liang len++; 1134dcb4e102SKan Liang len++; 1135dcb4e102SKan Liang } 1136dcb4e102SKan Liang perf_pmu_events_list = malloc(sizeof(struct perf_pmu_event_symbol) * len); 1137dcb4e102SKan Liang if (!perf_pmu_events_list) 1138dcb4e102SKan Liang return; 1139dcb4e102SKan Liang perf_pmu_events_list_num = len; 1140dcb4e102SKan Liang 1141dcb4e102SKan Liang len = 0; 1142dcb4e102SKan Liang list_for_each_entry(alias, &pmu->aliases, list) { 1143dcb4e102SKan Liang struct perf_pmu_event_symbol *p = perf_pmu_events_list + len; 1144dcb4e102SKan Liang char *tmp = strchr(alias->name, '-'); 1145dcb4e102SKan Liang 1146dcb4e102SKan Liang if (tmp != NULL) { 1147dcb4e102SKan Liang SET_SYMBOL(strndup(alias->name, tmp - alias->name), 1148dcb4e102SKan Liang PMU_EVENT_SYMBOL_PREFIX); 1149dcb4e102SKan Liang p++; 1150dcb4e102SKan Liang SET_SYMBOL(strdup(++tmp), PMU_EVENT_SYMBOL_SUFFIX); 1151dcb4e102SKan Liang len += 2; 1152dcb4e102SKan Liang } else { 1153dcb4e102SKan Liang SET_SYMBOL(strdup(alias->name), PMU_EVENT_SYMBOL); 1154dcb4e102SKan Liang len++; 1155dcb4e102SKan Liang } 1156dcb4e102SKan Liang } 1157dcb4e102SKan Liang qsort(perf_pmu_events_list, len, 1158dcb4e102SKan Liang sizeof(struct perf_pmu_event_symbol), comp_pmu); 1159dcb4e102SKan Liang 1160dcb4e102SKan Liang return; 1161dcb4e102SKan Liang err: 1162dcb4e102SKan Liang perf_pmu__parse_cleanup(); 1163dcb4e102SKan Liang } 1164dcb4e102SKan Liang 1165dcb4e102SKan Liang enum perf_pmu_event_symbol_type 1166dcb4e102SKan Liang perf_pmu__parse_check(const char *name) 1167dcb4e102SKan Liang { 1168dcb4e102SKan Liang struct perf_pmu_event_symbol p, *r; 1169dcb4e102SKan Liang 1170dcb4e102SKan Liang /* scan kernel pmu events from sysfs if needed */ 1171dcb4e102SKan Liang if (perf_pmu_events_list_num == 0) 1172dcb4e102SKan Liang perf_pmu__parse_init(); 1173dcb4e102SKan Liang /* 1174dcb4e102SKan Liang * name "cpu" could be prefix of cpu-cycles or cpu// events. 1175dcb4e102SKan Liang * cpu-cycles has been handled by hardcode. 1176dcb4e102SKan Liang * So it must be cpu// events, not kernel pmu event. 1177dcb4e102SKan Liang */ 1178dcb4e102SKan Liang if ((perf_pmu_events_list_num <= 0) || !strcmp(name, "cpu")) 1179dcb4e102SKan Liang return PMU_EVENT_SYMBOL_ERR; 1180dcb4e102SKan Liang 1181dcb4e102SKan Liang p.symbol = strdup(name); 1182dcb4e102SKan Liang r = bsearch(&p, perf_pmu_events_list, 1183dcb4e102SKan Liang (size_t) perf_pmu_events_list_num, 1184dcb4e102SKan Liang sizeof(struct perf_pmu_event_symbol), comp_pmu); 1185dcb4e102SKan Liang free(p.symbol); 1186dcb4e102SKan Liang return r ? r->type : PMU_EVENT_SYMBOL_ERR; 1187dcb4e102SKan Liang } 1188dcb4e102SKan Liang 118990e2b22dSJiri Olsa static int parse_events__scanner(const char *str, void *data, int start_token) 1190ac20de6fSZheng Yan { 1191ac20de6fSZheng Yan YY_BUFFER_STATE buffer; 1192ac20de6fSZheng Yan void *scanner; 1193ac20de6fSZheng Yan int ret; 1194ac20de6fSZheng Yan 119590e2b22dSJiri Olsa ret = parse_events_lex_init_extra(start_token, &scanner); 1196ac20de6fSZheng Yan if (ret) 1197ac20de6fSZheng Yan return ret; 1198ac20de6fSZheng Yan 1199ac20de6fSZheng Yan buffer = parse_events__scan_string(str, scanner); 1200ac20de6fSZheng Yan 1201ac20de6fSZheng Yan #ifdef PARSER_DEBUG 1202ac20de6fSZheng Yan parse_events_debug = 1; 1203ac20de6fSZheng Yan #endif 1204ac20de6fSZheng Yan ret = parse_events_parse(data, scanner); 1205ac20de6fSZheng Yan 1206ac20de6fSZheng Yan parse_events__flush_buffer(buffer, scanner); 1207ac20de6fSZheng Yan parse_events__delete_buffer(buffer, scanner); 1208ac20de6fSZheng Yan parse_events_lex_destroy(scanner); 1209ac20de6fSZheng Yan return ret; 1210ac20de6fSZheng Yan } 1211ac20de6fSZheng Yan 121290e2b22dSJiri Olsa /* 121390e2b22dSJiri Olsa * parse event config string, return a list of event terms. 121490e2b22dSJiri Olsa */ 121590e2b22dSJiri Olsa int parse_events_terms(struct list_head *terms, const char *str) 121690e2b22dSJiri Olsa { 121723b6339bSArnaldo Carvalho de Melo struct parse_events_terms data = { 121890e2b22dSJiri Olsa .terms = NULL, 121990e2b22dSJiri Olsa }; 122090e2b22dSJiri Olsa int ret; 122190e2b22dSJiri Olsa 122290e2b22dSJiri Olsa ret = parse_events__scanner(str, &data, PE_START_TERMS); 122390e2b22dSJiri Olsa if (!ret) { 122490e2b22dSJiri Olsa list_splice(data.terms, terms); 122574cf249dSArnaldo Carvalho de Melo zfree(&data.terms); 122690e2b22dSJiri Olsa return 0; 122790e2b22dSJiri Olsa } 122890e2b22dSJiri Olsa 1229b2c34fdeSAdrian Hunter if (data.terms) 123090e2b22dSJiri Olsa parse_events__free_terms(data.terms); 123190e2b22dSJiri Olsa return ret; 123290e2b22dSJiri Olsa } 123390e2b22dSJiri Olsa 1234b39b8393SJiri Olsa int parse_events(struct perf_evlist *evlist, const char *str, 1235b39b8393SJiri Olsa struct parse_events_error *err) 123686470930SIngo Molnar { 123723b6339bSArnaldo Carvalho de Melo struct parse_events_evlist data = { 123846010ab2SJiri Olsa .list = LIST_HEAD_INIT(data.list), 123946010ab2SJiri Olsa .idx = evlist->nr_entries, 1240b39b8393SJiri Olsa .error = err, 124146010ab2SJiri Olsa }; 124246010ab2SJiri Olsa int ret; 124386470930SIngo Molnar 124490e2b22dSJiri Olsa ret = parse_events__scanner(str, &data, PE_START_EVENTS); 1245dcb4e102SKan Liang perf_pmu__parse_cleanup(); 124689812fc8SJiri Olsa if (!ret) { 124715bfd2ccSWang Nan struct perf_evsel *last; 124815bfd2ccSWang Nan 1249854f7363SWang Nan if (list_empty(&data.list)) { 1250854f7363SWang Nan WARN_ONCE(true, "WARNING: event parser found nothing"); 1251854f7363SWang Nan return -1; 1252854f7363SWang Nan } 1253854f7363SWang Nan 1254f114d6efSAdrian Hunter perf_evlist__splice_list_tail(evlist, &data.list); 125597f63e4aSNamhyung Kim evlist->nr_groups += data.nr_groups; 125615bfd2ccSWang Nan last = perf_evlist__last(evlist); 125715bfd2ccSWang Nan last->cmdline_group_boundary = true; 125815bfd2ccSWang Nan 125986470930SIngo Molnar return 0; 126086470930SIngo Molnar } 126186470930SIngo Molnar 12625d7be90eSJiri Olsa /* 12635d7be90eSJiri Olsa * There are 2 users - builtin-record and builtin-test objects. 12645d7be90eSJiri Olsa * Both call perf_evlist__delete in case of error, so we dont 12655d7be90eSJiri Olsa * need to bother. 12665d7be90eSJiri Olsa */ 126789812fc8SJiri Olsa return ret; 126889812fc8SJiri Olsa } 126989812fc8SJiri Olsa 1270b39b8393SJiri Olsa #define MAX_WIDTH 1000 1271b39b8393SJiri Olsa static int get_term_width(void) 1272b39b8393SJiri Olsa { 1273b39b8393SJiri Olsa struct winsize ws; 1274b39b8393SJiri Olsa 1275b39b8393SJiri Olsa get_term_dimensions(&ws); 1276b39b8393SJiri Olsa return ws.ws_col > MAX_WIDTH ? MAX_WIDTH : ws.ws_col; 1277b39b8393SJiri Olsa } 1278b39b8393SJiri Olsa 1279b39b8393SJiri Olsa static void parse_events_print_error(struct parse_events_error *err, 1280b39b8393SJiri Olsa const char *event) 1281b39b8393SJiri Olsa { 1282b39b8393SJiri Olsa const char *str = "invalid or unsupported event: "; 1283b39b8393SJiri Olsa char _buf[MAX_WIDTH]; 1284b39b8393SJiri Olsa char *buf = (char *) event; 1285b39b8393SJiri Olsa int idx = 0; 1286b39b8393SJiri Olsa 1287b39b8393SJiri Olsa if (err->str) { 1288b39b8393SJiri Olsa /* -2 for extra '' in the final fprintf */ 1289b39b8393SJiri Olsa int width = get_term_width() - 2; 1290b39b8393SJiri Olsa int len_event = strlen(event); 1291b39b8393SJiri Olsa int len_str, max_len, cut = 0; 1292b39b8393SJiri Olsa 1293b39b8393SJiri Olsa /* 1294b39b8393SJiri Olsa * Maximum error index indent, we will cut 1295b39b8393SJiri Olsa * the event string if it's bigger. 1296b39b8393SJiri Olsa */ 1297141b2d31SAdrian Hunter int max_err_idx = 13; 1298b39b8393SJiri Olsa 1299b39b8393SJiri Olsa /* 1300b39b8393SJiri Olsa * Let's be specific with the message when 1301b39b8393SJiri Olsa * we have the precise error. 1302b39b8393SJiri Olsa */ 1303b39b8393SJiri Olsa str = "event syntax error: "; 1304b39b8393SJiri Olsa len_str = strlen(str); 1305b39b8393SJiri Olsa max_len = width - len_str; 1306b39b8393SJiri Olsa 1307b39b8393SJiri Olsa buf = _buf; 1308b39b8393SJiri Olsa 1309b39b8393SJiri Olsa /* We're cutting from the beggining. */ 1310b39b8393SJiri Olsa if (err->idx > max_err_idx) 1311b39b8393SJiri Olsa cut = err->idx - max_err_idx; 1312b39b8393SJiri Olsa 1313b39b8393SJiri Olsa strncpy(buf, event + cut, max_len); 1314b39b8393SJiri Olsa 1315b39b8393SJiri Olsa /* Mark cut parts with '..' on both sides. */ 1316b39b8393SJiri Olsa if (cut) 1317b39b8393SJiri Olsa buf[0] = buf[1] = '.'; 1318b39b8393SJiri Olsa 1319b39b8393SJiri Olsa if ((len_event - cut) > max_len) { 1320b39b8393SJiri Olsa buf[max_len - 1] = buf[max_len - 2] = '.'; 1321b39b8393SJiri Olsa buf[max_len] = 0; 1322b39b8393SJiri Olsa } 1323b39b8393SJiri Olsa 1324b39b8393SJiri Olsa idx = len_str + err->idx - cut; 1325b39b8393SJiri Olsa } 1326b39b8393SJiri Olsa 1327b39b8393SJiri Olsa fprintf(stderr, "%s'%s'\n", str, buf); 1328b39b8393SJiri Olsa if (idx) { 1329b39b8393SJiri Olsa fprintf(stderr, "%*s\\___ %s\n", idx + 1, "", err->str); 1330b39b8393SJiri Olsa if (err->help) 1331b39b8393SJiri Olsa fprintf(stderr, "\n%s\n", err->help); 1332b39b8393SJiri Olsa free(err->str); 1333b39b8393SJiri Olsa free(err->help); 1334b39b8393SJiri Olsa } 1335b39b8393SJiri Olsa 1336b39b8393SJiri Olsa fprintf(stderr, "Run 'perf list' for a list of valid events\n"); 1337b39b8393SJiri Olsa } 1338b39b8393SJiri Olsa 1339b39b8393SJiri Olsa #undef MAX_WIDTH 1340b39b8393SJiri Olsa 1341f120f9d5SJiri Olsa int parse_events_option(const struct option *opt, const char *str, 13421d037ca1SIrina Tirdea int unset __maybe_unused) 1343f120f9d5SJiri Olsa { 1344f120f9d5SJiri Olsa struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 1345b39b8393SJiri Olsa struct parse_events_error err = { .idx = 0, }; 1346b39b8393SJiri Olsa int ret = parse_events(evlist, str, &err); 13479175ce1fSAndi Kleen 1348b39b8393SJiri Olsa if (ret) 1349b39b8393SJiri Olsa parse_events_print_error(&err, str); 1350b39b8393SJiri Olsa 13519175ce1fSAndi Kleen return ret; 1352f120f9d5SJiri Olsa } 1353f120f9d5SJiri Olsa 13544ba1faa1SWang Nan static int 13554ba1faa1SWang Nan foreach_evsel_in_last_glob(struct perf_evlist *evlist, 13564ba1faa1SWang Nan int (*func)(struct perf_evsel *evsel, 13574ba1faa1SWang Nan const void *arg), 13584ba1faa1SWang Nan const void *arg) 1359c171b552SLi Zefan { 136069aad6f1SArnaldo Carvalho de Melo struct perf_evsel *last = NULL; 13614ba1faa1SWang Nan int err; 1362c171b552SLi Zefan 1363854f7363SWang Nan /* 1364854f7363SWang Nan * Don't return when list_empty, give func a chance to report 1365854f7363SWang Nan * error when it found last == NULL. 1366854f7363SWang Nan * 1367854f7363SWang Nan * So no need to WARN here, let *func do this. 1368854f7363SWang Nan */ 1369361c99a6SArnaldo Carvalho de Melo if (evlist->nr_entries > 0) 13700c21f736SArnaldo Carvalho de Melo last = perf_evlist__last(evlist); 137169aad6f1SArnaldo Carvalho de Melo 137215bfd2ccSWang Nan do { 13734ba1faa1SWang Nan err = (*func)(last, arg); 13744ba1faa1SWang Nan if (err) 1375c171b552SLi Zefan return -1; 13764ba1faa1SWang Nan if (!last) 13774ba1faa1SWang Nan return 0; 1378c171b552SLi Zefan 137915bfd2ccSWang Nan if (last->node.prev == &evlist->entries) 138015bfd2ccSWang Nan return 0; 138115bfd2ccSWang Nan last = list_entry(last->node.prev, struct perf_evsel, node); 138215bfd2ccSWang Nan } while (!last->cmdline_group_boundary); 138315bfd2ccSWang Nan 1384c171b552SLi Zefan return 0; 1385c171b552SLi Zefan } 1386c171b552SLi Zefan 13874ba1faa1SWang Nan static int set_filter(struct perf_evsel *evsel, const void *arg) 13884ba1faa1SWang Nan { 13894ba1faa1SWang Nan const char *str = arg; 13904ba1faa1SWang Nan 13914ba1faa1SWang Nan if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) { 13924ba1faa1SWang Nan fprintf(stderr, 13934ba1faa1SWang Nan "--filter option should follow a -e tracepoint option\n"); 13944ba1faa1SWang Nan return -1; 13954ba1faa1SWang Nan } 13964ba1faa1SWang Nan 13974ba1faa1SWang Nan if (perf_evsel__append_filter(evsel, "&&", str) < 0) { 13984ba1faa1SWang Nan fprintf(stderr, 13994ba1faa1SWang Nan "not enough memory to hold filter string\n"); 14004ba1faa1SWang Nan return -1; 14014ba1faa1SWang Nan } 14024ba1faa1SWang Nan 14034ba1faa1SWang Nan return 0; 14044ba1faa1SWang Nan } 14054ba1faa1SWang Nan 14064ba1faa1SWang Nan int parse_filter(const struct option *opt, const char *str, 14074ba1faa1SWang Nan int unset __maybe_unused) 14084ba1faa1SWang Nan { 14094ba1faa1SWang Nan struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 14104ba1faa1SWang Nan 14114ba1faa1SWang Nan return foreach_evsel_in_last_glob(evlist, set_filter, 14124ba1faa1SWang Nan (const void *)str); 14134ba1faa1SWang Nan } 14144ba1faa1SWang Nan 14154ba1faa1SWang Nan static int add_exclude_perf_filter(struct perf_evsel *evsel, 14164ba1faa1SWang Nan const void *arg __maybe_unused) 14174ba1faa1SWang Nan { 14184ba1faa1SWang Nan char new_filter[64]; 14194ba1faa1SWang Nan 14204ba1faa1SWang Nan if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) { 14214ba1faa1SWang Nan fprintf(stderr, 14224ba1faa1SWang Nan "--exclude-perf option should follow a -e tracepoint option\n"); 14234ba1faa1SWang Nan return -1; 14244ba1faa1SWang Nan } 14254ba1faa1SWang Nan 14264ba1faa1SWang Nan snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid()); 14274ba1faa1SWang Nan 14284ba1faa1SWang Nan if (perf_evsel__append_filter(evsel, "&&", new_filter) < 0) { 14294ba1faa1SWang Nan fprintf(stderr, 14304ba1faa1SWang Nan "not enough memory to hold filter string\n"); 14314ba1faa1SWang Nan return -1; 14324ba1faa1SWang Nan } 14334ba1faa1SWang Nan 14344ba1faa1SWang Nan return 0; 14354ba1faa1SWang Nan } 14364ba1faa1SWang Nan 14374ba1faa1SWang Nan int exclude_perf(const struct option *opt, 14384ba1faa1SWang Nan const char *arg __maybe_unused, 14394ba1faa1SWang Nan int unset __maybe_unused) 14404ba1faa1SWang Nan { 14414ba1faa1SWang Nan struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 14424ba1faa1SWang Nan 14434ba1faa1SWang Nan return foreach_evsel_in_last_glob(evlist, add_exclude_perf_filter, 14444ba1faa1SWang Nan NULL); 14454ba1faa1SWang Nan } 14464ba1faa1SWang Nan 144786470930SIngo Molnar static const char * const event_type_descriptors[] = { 144886470930SIngo Molnar "Hardware event", 144986470930SIngo Molnar "Software event", 145086470930SIngo Molnar "Tracepoint event", 145186470930SIngo Molnar "Hardware cache event", 145241bdcb23SLiming Wang "Raw hardware event descriptor", 145341bdcb23SLiming Wang "Hardware breakpoint", 145486470930SIngo Molnar }; 145586470930SIngo Molnar 1456ab0e4800SYunlong Song static int cmp_string(const void *a, const void *b) 1457ab0e4800SYunlong Song { 1458ab0e4800SYunlong Song const char * const *as = a; 1459ab0e4800SYunlong Song const char * const *bs = b; 1460ab0e4800SYunlong Song 1461ab0e4800SYunlong Song return strcmp(*as, *bs); 1462ab0e4800SYunlong Song } 1463ab0e4800SYunlong Song 146486470930SIngo Molnar /* 1465f6bdafefSJason Baron * Print the events from <debugfs_mount_point>/tracing/events 1466f6bdafefSJason Baron */ 1467f6bdafefSJason Baron 1468a3277d2dSFrederic Weisbecker void print_tracepoint_events(const char *subsys_glob, const char *event_glob, 1469a3277d2dSFrederic Weisbecker bool name_only) 1470f6bdafefSJason Baron { 1471f6bdafefSJason Baron DIR *sys_dir, *evt_dir; 1472f6bdafefSJason Baron struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 1473f6bdafefSJason Baron char evt_path[MAXPATHLEN]; 1474725b1368SEric Dumazet char dir_path[MAXPATHLEN]; 1475ab0e4800SYunlong Song char **evt_list = NULL; 1476ab0e4800SYunlong Song unsigned int evt_i = 0, evt_num = 0; 1477ab0e4800SYunlong Song bool evt_num_known = false; 1478f6bdafefSJason Baron 1479ab0e4800SYunlong Song restart: 1480ebf294bfSArnaldo Carvalho de Melo sys_dir = opendir(tracing_events_path); 1481f6bdafefSJason Baron if (!sys_dir) 1482725b1368SEric Dumazet return; 1483f6bdafefSJason Baron 1484ab0e4800SYunlong Song if (evt_num_known) { 1485ab0e4800SYunlong Song evt_list = zalloc(sizeof(char *) * evt_num); 1486ab0e4800SYunlong Song if (!evt_list) 1487ab0e4800SYunlong Song goto out_close_sys_dir; 1488ab0e4800SYunlong Song } 1489ab0e4800SYunlong Song 14906b58e7f1SUlrich Drepper for_each_subsystem(sys_dir, sys_dirent, sys_next) { 1491668b8788SArnaldo Carvalho de Melo if (subsys_glob != NULL && 1492668b8788SArnaldo Carvalho de Melo !strglobmatch(sys_dirent.d_name, subsys_glob)) 1493668b8788SArnaldo Carvalho de Melo continue; 1494725b1368SEric Dumazet 1495ebf294bfSArnaldo Carvalho de Melo snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path, 1496725b1368SEric Dumazet sys_dirent.d_name); 1497725b1368SEric Dumazet evt_dir = opendir(dir_path); 1498725b1368SEric Dumazet if (!evt_dir) 14996b58e7f1SUlrich Drepper continue; 1500725b1368SEric Dumazet 15016b58e7f1SUlrich Drepper for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 1502668b8788SArnaldo Carvalho de Melo if (event_glob != NULL && 1503668b8788SArnaldo Carvalho de Melo !strglobmatch(evt_dirent.d_name, event_glob)) 1504668b8788SArnaldo Carvalho de Melo continue; 1505668b8788SArnaldo Carvalho de Melo 1506ab0e4800SYunlong Song if (!evt_num_known) { 1507ab0e4800SYunlong Song evt_num++; 1508a3277d2dSFrederic Weisbecker continue; 1509a3277d2dSFrederic Weisbecker } 1510a3277d2dSFrederic Weisbecker 1511f6bdafefSJason Baron snprintf(evt_path, MAXPATHLEN, "%s:%s", 1512f6bdafefSJason Baron sys_dirent.d_name, evt_dirent.d_name); 1513ab0e4800SYunlong Song 1514ab0e4800SYunlong Song evt_list[evt_i] = strdup(evt_path); 1515ab0e4800SYunlong Song if (evt_list[evt_i] == NULL) 1516ab0e4800SYunlong Song goto out_close_evt_dir; 1517ab0e4800SYunlong Song evt_i++; 1518f6bdafefSJason Baron } 1519f6bdafefSJason Baron closedir(evt_dir); 1520f6bdafefSJason Baron } 1521f6bdafefSJason Baron closedir(sys_dir); 1522ab0e4800SYunlong Song 1523ab0e4800SYunlong Song if (!evt_num_known) { 1524ab0e4800SYunlong Song evt_num_known = true; 1525ab0e4800SYunlong Song goto restart; 1526ab0e4800SYunlong Song } 1527ab0e4800SYunlong Song qsort(evt_list, evt_num, sizeof(char *), cmp_string); 1528ab0e4800SYunlong Song evt_i = 0; 1529ab0e4800SYunlong Song while (evt_i < evt_num) { 1530ab0e4800SYunlong Song if (name_only) { 1531ab0e4800SYunlong Song printf("%s ", evt_list[evt_i++]); 1532ab0e4800SYunlong Song continue; 1533ab0e4800SYunlong Song } 1534ab0e4800SYunlong Song printf(" %-50s [%s]\n", evt_list[evt_i++], 1535ab0e4800SYunlong Song event_type_descriptors[PERF_TYPE_TRACEPOINT]); 1536ab0e4800SYunlong Song } 1537*dfc431cbSArnaldo Carvalho de Melo if (evt_num && pager_in_use()) 1538ab0e4800SYunlong Song printf("\n"); 1539ab0e4800SYunlong Song 1540ab0e4800SYunlong Song out_free: 1541ab0e4800SYunlong Song evt_num = evt_i; 1542ab0e4800SYunlong Song for (evt_i = 0; evt_i < evt_num; evt_i++) 1543ab0e4800SYunlong Song zfree(&evt_list[evt_i]); 1544ab0e4800SYunlong Song zfree(&evt_list); 1545ab0e4800SYunlong Song return; 1546ab0e4800SYunlong Song 1547ab0e4800SYunlong Song out_close_evt_dir: 1548ab0e4800SYunlong Song closedir(evt_dir); 1549ab0e4800SYunlong Song out_close_sys_dir: 1550ab0e4800SYunlong Song closedir(sys_dir); 1551ab0e4800SYunlong Song 1552ab0e4800SYunlong Song printf("FATAL: not enough memory to print %s\n", 1553ab0e4800SYunlong Song event_type_descriptors[PERF_TYPE_TRACEPOINT]); 1554ab0e4800SYunlong Song if (evt_list) 1555ab0e4800SYunlong Song goto out_free; 1556f6bdafefSJason Baron } 1557f6bdafefSJason Baron 1558f6bdafefSJason Baron /* 155920c457b8SThomas Renninger * Check whether event is in <debugfs_mount_point>/tracing/events 156020c457b8SThomas Renninger */ 156120c457b8SThomas Renninger 156220c457b8SThomas Renninger int is_valid_tracepoint(const char *event_string) 156320c457b8SThomas Renninger { 156420c457b8SThomas Renninger DIR *sys_dir, *evt_dir; 156520c457b8SThomas Renninger struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 156620c457b8SThomas Renninger char evt_path[MAXPATHLEN]; 156720c457b8SThomas Renninger char dir_path[MAXPATHLEN]; 156820c457b8SThomas Renninger 1569ebf294bfSArnaldo Carvalho de Melo sys_dir = opendir(tracing_events_path); 157020c457b8SThomas Renninger if (!sys_dir) 157120c457b8SThomas Renninger return 0; 157220c457b8SThomas Renninger 157320c457b8SThomas Renninger for_each_subsystem(sys_dir, sys_dirent, sys_next) { 157420c457b8SThomas Renninger 1575ebf294bfSArnaldo Carvalho de Melo snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path, 157620c457b8SThomas Renninger sys_dirent.d_name); 157720c457b8SThomas Renninger evt_dir = opendir(dir_path); 157820c457b8SThomas Renninger if (!evt_dir) 157920c457b8SThomas Renninger continue; 158020c457b8SThomas Renninger 158120c457b8SThomas Renninger for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 158220c457b8SThomas Renninger snprintf(evt_path, MAXPATHLEN, "%s:%s", 158320c457b8SThomas Renninger sys_dirent.d_name, evt_dirent.d_name); 158420c457b8SThomas Renninger if (!strcmp(evt_path, event_string)) { 158520c457b8SThomas Renninger closedir(evt_dir); 158620c457b8SThomas Renninger closedir(sys_dir); 158720c457b8SThomas Renninger return 1; 158820c457b8SThomas Renninger } 158920c457b8SThomas Renninger } 159020c457b8SThomas Renninger closedir(evt_dir); 159120c457b8SThomas Renninger } 159220c457b8SThomas Renninger closedir(sys_dir); 159320c457b8SThomas Renninger return 0; 159420c457b8SThomas Renninger } 159520c457b8SThomas Renninger 1596b41f1cecSNamhyung Kim static bool is_event_supported(u8 type, unsigned config) 1597b41f1cecSNamhyung Kim { 1598b41f1cecSNamhyung Kim bool ret = true; 159988fee52eSVince Weaver int open_return; 1600b41f1cecSNamhyung Kim struct perf_evsel *evsel; 1601b41f1cecSNamhyung Kim struct perf_event_attr attr = { 1602b41f1cecSNamhyung Kim .type = type, 1603b41f1cecSNamhyung Kim .config = config, 1604b41f1cecSNamhyung Kim .disabled = 1, 1605b41f1cecSNamhyung Kim }; 1606b41f1cecSNamhyung Kim struct { 1607b41f1cecSNamhyung Kim struct thread_map map; 1608b41f1cecSNamhyung Kim int threads[1]; 1609b41f1cecSNamhyung Kim } tmap = { 1610b41f1cecSNamhyung Kim .map.nr = 1, 1611b41f1cecSNamhyung Kim .threads = { 0 }, 1612b41f1cecSNamhyung Kim }; 1613b41f1cecSNamhyung Kim 1614ef503831SArnaldo Carvalho de Melo evsel = perf_evsel__new(&attr); 1615b41f1cecSNamhyung Kim if (evsel) { 161688fee52eSVince Weaver open_return = perf_evsel__open(evsel, NULL, &tmap.map); 161788fee52eSVince Weaver ret = open_return >= 0; 161888fee52eSVince Weaver 161988fee52eSVince Weaver if (open_return == -EACCES) { 162088fee52eSVince Weaver /* 162188fee52eSVince Weaver * This happens if the paranoid value 162288fee52eSVince Weaver * /proc/sys/kernel/perf_event_paranoid is set to 2 162388fee52eSVince Weaver * Re-run with exclude_kernel set; we don't do that 162488fee52eSVince Weaver * by default as some ARM machines do not support it. 162588fee52eSVince Weaver * 162688fee52eSVince Weaver */ 162788fee52eSVince Weaver evsel->attr.exclude_kernel = 1; 1628b41f1cecSNamhyung Kim ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0; 162988fee52eSVince Weaver } 1630b41f1cecSNamhyung Kim perf_evsel__delete(evsel); 1631b41f1cecSNamhyung Kim } 1632b41f1cecSNamhyung Kim 1633b41f1cecSNamhyung Kim return ret; 1634b41f1cecSNamhyung Kim } 1635b41f1cecSNamhyung Kim 1636a3277d2dSFrederic Weisbecker int print_hwcache_events(const char *event_glob, bool name_only) 1637668b8788SArnaldo Carvalho de Melo { 1638ab0e4800SYunlong Song unsigned int type, op, i, evt_i = 0, evt_num = 0; 16390b668bc9SArnaldo Carvalho de Melo char name[64]; 1640ab0e4800SYunlong Song char **evt_list = NULL; 1641ab0e4800SYunlong Song bool evt_num_known = false; 1642ab0e4800SYunlong Song 1643ab0e4800SYunlong Song restart: 1644ab0e4800SYunlong Song if (evt_num_known) { 1645ab0e4800SYunlong Song evt_list = zalloc(sizeof(char *) * evt_num); 1646ab0e4800SYunlong Song if (!evt_list) 1647ab0e4800SYunlong Song goto out_enomem; 1648ab0e4800SYunlong Song } 1649668b8788SArnaldo Carvalho de Melo 1650668b8788SArnaldo Carvalho de Melo for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 1651668b8788SArnaldo Carvalho de Melo for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 1652668b8788SArnaldo Carvalho de Melo /* skip invalid cache type */ 16530b668bc9SArnaldo Carvalho de Melo if (!perf_evsel__is_cache_op_valid(type, op)) 1654668b8788SArnaldo Carvalho de Melo continue; 1655668b8788SArnaldo Carvalho de Melo 1656668b8788SArnaldo Carvalho de Melo for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { 16570b668bc9SArnaldo Carvalho de Melo __perf_evsel__hw_cache_type_op_res_name(type, op, i, 16580b668bc9SArnaldo Carvalho de Melo name, sizeof(name)); 1659947b4ad1SIngo Molnar if (event_glob != NULL && !strglobmatch(name, event_glob)) 1660668b8788SArnaldo Carvalho de Melo continue; 1661668b8788SArnaldo Carvalho de Melo 1662b41f1cecSNamhyung Kim if (!is_event_supported(PERF_TYPE_HW_CACHE, 1663b41f1cecSNamhyung Kim type | (op << 8) | (i << 16))) 1664b41f1cecSNamhyung Kim continue; 1665b41f1cecSNamhyung Kim 1666ab0e4800SYunlong Song if (!evt_num_known) { 1667ab0e4800SYunlong Song evt_num++; 1668ab0e4800SYunlong Song continue; 1669ab0e4800SYunlong Song } 1670ab0e4800SYunlong Song 1671ab0e4800SYunlong Song evt_list[evt_i] = strdup(name); 1672ab0e4800SYunlong Song if (evt_list[evt_i] == NULL) 1673ab0e4800SYunlong Song goto out_enomem; 1674ab0e4800SYunlong Song evt_i++; 1675668b8788SArnaldo Carvalho de Melo } 1676668b8788SArnaldo Carvalho de Melo } 1677668b8788SArnaldo Carvalho de Melo } 1678668b8788SArnaldo Carvalho de Melo 1679ab0e4800SYunlong Song if (!evt_num_known) { 1680ab0e4800SYunlong Song evt_num_known = true; 1681ab0e4800SYunlong Song goto restart; 1682ab0e4800SYunlong Song } 1683ab0e4800SYunlong Song qsort(evt_list, evt_num, sizeof(char *), cmp_string); 1684ab0e4800SYunlong Song evt_i = 0; 1685ab0e4800SYunlong Song while (evt_i < evt_num) { 1686ab0e4800SYunlong Song if (name_only) { 1687ab0e4800SYunlong Song printf("%s ", evt_list[evt_i++]); 1688ab0e4800SYunlong Song continue; 1689ab0e4800SYunlong Song } 1690ab0e4800SYunlong Song printf(" %-50s [%s]\n", evt_list[evt_i++], 1691ab0e4800SYunlong Song event_type_descriptors[PERF_TYPE_HW_CACHE]); 1692ab0e4800SYunlong Song } 1693*dfc431cbSArnaldo Carvalho de Melo if (evt_num && pager_in_use()) 1694dc098b35SAndi Kleen printf("\n"); 1695ab0e4800SYunlong Song 1696ab0e4800SYunlong Song out_free: 1697ab0e4800SYunlong Song evt_num = evt_i; 1698ab0e4800SYunlong Song for (evt_i = 0; evt_i < evt_num; evt_i++) 1699ab0e4800SYunlong Song zfree(&evt_list[evt_i]); 1700ab0e4800SYunlong Song zfree(&evt_list); 1701ab0e4800SYunlong Song return evt_num; 1702ab0e4800SYunlong Song 1703ab0e4800SYunlong Song out_enomem: 1704ab0e4800SYunlong Song printf("FATAL: not enough memory to print %s\n", event_type_descriptors[PERF_TYPE_HW_CACHE]); 1705ab0e4800SYunlong Song if (evt_list) 1706ab0e4800SYunlong Song goto out_free; 1707ab0e4800SYunlong Song return evt_num; 1708668b8788SArnaldo Carvalho de Melo } 1709668b8788SArnaldo Carvalho de Melo 1710705750f2SYunlong Song void print_symbol_events(const char *event_glob, unsigned type, 1711a3277d2dSFrederic Weisbecker struct event_symbol *syms, unsigned max, 1712a3277d2dSFrederic Weisbecker bool name_only) 171386470930SIngo Molnar { 1714ab0e4800SYunlong Song unsigned int i, evt_i = 0, evt_num = 0; 1715947b4ad1SIngo Molnar char name[MAX_NAME_LEN]; 1716ab0e4800SYunlong Song char **evt_list = NULL; 1717ab0e4800SYunlong Song bool evt_num_known = false; 1718ab0e4800SYunlong Song 1719ab0e4800SYunlong Song restart: 1720ab0e4800SYunlong Song if (evt_num_known) { 1721ab0e4800SYunlong Song evt_list = zalloc(sizeof(char *) * evt_num); 1722ab0e4800SYunlong Song if (!evt_list) 1723ab0e4800SYunlong Song goto out_enomem; 1724ab0e4800SYunlong Song syms -= max; 1725ab0e4800SYunlong Song } 172686470930SIngo Molnar 17271dc12760SJiri Olsa for (i = 0; i < max; i++, syms++) { 1728668b8788SArnaldo Carvalho de Melo 1729668b8788SArnaldo Carvalho de Melo if (event_glob != NULL && 1730668b8788SArnaldo Carvalho de Melo !(strglobmatch(syms->symbol, event_glob) || 1731668b8788SArnaldo Carvalho de Melo (syms->alias && strglobmatch(syms->alias, event_glob)))) 1732668b8788SArnaldo Carvalho de Melo continue; 173386470930SIngo Molnar 1734b41f1cecSNamhyung Kim if (!is_event_supported(type, i)) 1735b41f1cecSNamhyung Kim continue; 1736b41f1cecSNamhyung Kim 1737ab0e4800SYunlong Song if (!evt_num_known) { 1738ab0e4800SYunlong Song evt_num++; 1739a3277d2dSFrederic Weisbecker continue; 1740a3277d2dSFrederic Weisbecker } 1741a3277d2dSFrederic Weisbecker 1742ab0e4800SYunlong Song if (!name_only && strlen(syms->alias)) 1743947b4ad1SIngo Molnar snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); 174474d5b588SJaswinder Singh Rajput else 1745947b4ad1SIngo Molnar strncpy(name, syms->symbol, MAX_NAME_LEN); 174686470930SIngo Molnar 1747ab0e4800SYunlong Song evt_list[evt_i] = strdup(name); 1748ab0e4800SYunlong Song if (evt_list[evt_i] == NULL) 1749ab0e4800SYunlong Song goto out_enomem; 1750ab0e4800SYunlong Song evt_i++; 175186470930SIngo Molnar } 175286470930SIngo Molnar 1753ab0e4800SYunlong Song if (!evt_num_known) { 1754ab0e4800SYunlong Song evt_num_known = true; 1755ab0e4800SYunlong Song goto restart; 1756ab0e4800SYunlong Song } 1757ab0e4800SYunlong Song qsort(evt_list, evt_num, sizeof(char *), cmp_string); 1758ab0e4800SYunlong Song evt_i = 0; 1759ab0e4800SYunlong Song while (evt_i < evt_num) { 1760ab0e4800SYunlong Song if (name_only) { 1761ab0e4800SYunlong Song printf("%s ", evt_list[evt_i++]); 1762ab0e4800SYunlong Song continue; 1763ab0e4800SYunlong Song } 1764ab0e4800SYunlong Song printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]); 1765ab0e4800SYunlong Song } 1766*dfc431cbSArnaldo Carvalho de Melo if (evt_num && pager_in_use()) 1767689d3018SMarti Raudsepp printf("\n"); 1768ab0e4800SYunlong Song 1769ab0e4800SYunlong Song out_free: 1770ab0e4800SYunlong Song evt_num = evt_i; 1771ab0e4800SYunlong Song for (evt_i = 0; evt_i < evt_num; evt_i++) 1772ab0e4800SYunlong Song zfree(&evt_list[evt_i]); 1773ab0e4800SYunlong Song zfree(&evt_list); 1774ab0e4800SYunlong Song return; 1775ab0e4800SYunlong Song 1776ab0e4800SYunlong Song out_enomem: 1777ab0e4800SYunlong Song printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]); 1778ab0e4800SYunlong Song if (evt_list) 1779ab0e4800SYunlong Song goto out_free; 1780668b8788SArnaldo Carvalho de Melo } 17811dc12760SJiri Olsa 17821dc12760SJiri Olsa /* 17831dc12760SJiri Olsa * Print the help text for the event symbols: 17841dc12760SJiri Olsa */ 1785a3277d2dSFrederic Weisbecker void print_events(const char *event_glob, bool name_only) 17861dc12760SJiri Olsa { 17871dc12760SJiri Olsa print_symbol_events(event_glob, PERF_TYPE_HARDWARE, 1788a3277d2dSFrederic Weisbecker event_symbols_hw, PERF_COUNT_HW_MAX, name_only); 17891dc12760SJiri Olsa 17901dc12760SJiri Olsa print_symbol_events(event_glob, PERF_TYPE_SOFTWARE, 1791a3277d2dSFrederic Weisbecker event_symbols_sw, PERF_COUNT_SW_MAX, name_only); 17921dc12760SJiri Olsa 1793a3277d2dSFrederic Weisbecker print_hwcache_events(event_glob, name_only); 179473c24cb8SJaswinder Singh Rajput 1795dc098b35SAndi Kleen print_pmu_events(event_glob, name_only); 1796dc098b35SAndi Kleen 1797668b8788SArnaldo Carvalho de Melo if (event_glob != NULL) 1798668b8788SArnaldo Carvalho de Melo return; 179973c24cb8SJaswinder Singh Rajput 1800a3277d2dSFrederic Weisbecker if (!name_only) { 1801947b4ad1SIngo Molnar printf(" %-50s [%s]\n", 18025f537a26SJiri Olsa "rNNN", 18031cf4a063SArnaldo Carvalho de Melo event_type_descriptors[PERF_TYPE_RAW]); 18045f537a26SJiri Olsa printf(" %-50s [%s]\n", 18055f537a26SJiri Olsa "cpu/t1=v1[,t2=v2,t3 ...]/modifier", 18065f537a26SJiri Olsa event_type_descriptors[PERF_TYPE_RAW]); 1807*dfc431cbSArnaldo Carvalho de Melo if (pager_in_use()) 1808*dfc431cbSArnaldo Carvalho de Melo printf(" (see 'man perf-list' on how to encode it)\n\n"); 180986470930SIngo Molnar 1810947b4ad1SIngo Molnar printf(" %-50s [%s]\n", 18113741eb9fSJacob Shin "mem:<addr>[/len][:access]", 181241bdcb23SLiming Wang event_type_descriptors[PERF_TYPE_BREAKPOINT]); 1813*dfc431cbSArnaldo Carvalho de Melo if (pager_in_use()) 18141b290d67SFrederic Weisbecker printf("\n"); 1815a3277d2dSFrederic Weisbecker } 18161b290d67SFrederic Weisbecker 1817a3277d2dSFrederic Weisbecker print_tracepoint_events(NULL, NULL, name_only); 181886470930SIngo Molnar } 18198f707d84SJiri Olsa 18206cee6cd3SArnaldo Carvalho de Melo int parse_events__is_hardcoded_term(struct parse_events_term *term) 18218f707d84SJiri Olsa { 182216fa7e82SJiri Olsa return term->type_term != PARSE_EVENTS__TERM_TYPE_USER; 18238f707d84SJiri Olsa } 18248f707d84SJiri Olsa 18256cee6cd3SArnaldo Carvalho de Melo static int new_term(struct parse_events_term **_term, int type_val, 182616fa7e82SJiri Olsa int type_term, char *config, 1827cecf3a2eSJiri Olsa char *str, u64 num, int err_term, int err_val) 18288f707d84SJiri Olsa { 18296cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 18308f707d84SJiri Olsa 18318f707d84SJiri Olsa term = zalloc(sizeof(*term)); 18328f707d84SJiri Olsa if (!term) 18338f707d84SJiri Olsa return -ENOMEM; 18348f707d84SJiri Olsa 18358f707d84SJiri Olsa INIT_LIST_HEAD(&term->list); 183616fa7e82SJiri Olsa term->type_val = type_val; 183716fa7e82SJiri Olsa term->type_term = type_term; 18388f707d84SJiri Olsa term->config = config; 1839cecf3a2eSJiri Olsa term->err_term = err_term; 1840cecf3a2eSJiri Olsa term->err_val = err_val; 18418f707d84SJiri Olsa 184216fa7e82SJiri Olsa switch (type_val) { 18438f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_NUM: 18448f707d84SJiri Olsa term->val.num = num; 18458f707d84SJiri Olsa break; 18468f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_STR: 18478f707d84SJiri Olsa term->val.str = str; 18488f707d84SJiri Olsa break; 18498f707d84SJiri Olsa default: 18504be8be6bSAdrian Hunter free(term); 18518f707d84SJiri Olsa return -EINVAL; 18528f707d84SJiri Olsa } 18538f707d84SJiri Olsa 18548f707d84SJiri Olsa *_term = term; 18558f707d84SJiri Olsa return 0; 18568f707d84SJiri Olsa } 18578f707d84SJiri Olsa 18586cee6cd3SArnaldo Carvalho de Melo int parse_events_term__num(struct parse_events_term **term, 1859cecf3a2eSJiri Olsa int type_term, char *config, u64 num, 1860bb78ce7dSAdrian Hunter void *loc_term_, void *loc_val_) 186116fa7e82SJiri Olsa { 1862bb78ce7dSAdrian Hunter YYLTYPE *loc_term = loc_term_; 1863bb78ce7dSAdrian Hunter YYLTYPE *loc_val = loc_val_; 1864bb78ce7dSAdrian Hunter 186516fa7e82SJiri Olsa return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term, 1866cecf3a2eSJiri Olsa config, NULL, num, 1867cecf3a2eSJiri Olsa loc_term ? loc_term->first_column : 0, 1868cecf3a2eSJiri Olsa loc_val ? loc_val->first_column : 0); 186916fa7e82SJiri Olsa } 187016fa7e82SJiri Olsa 18716cee6cd3SArnaldo Carvalho de Melo int parse_events_term__str(struct parse_events_term **term, 1872cecf3a2eSJiri Olsa int type_term, char *config, char *str, 1873bb78ce7dSAdrian Hunter void *loc_term_, void *loc_val_) 187416fa7e82SJiri Olsa { 1875bb78ce7dSAdrian Hunter YYLTYPE *loc_term = loc_term_; 1876bb78ce7dSAdrian Hunter YYLTYPE *loc_val = loc_val_; 1877bb78ce7dSAdrian Hunter 187816fa7e82SJiri Olsa return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, type_term, 1879cecf3a2eSJiri Olsa config, str, 0, 1880cecf3a2eSJiri Olsa loc_term ? loc_term->first_column : 0, 1881cecf3a2eSJiri Olsa loc_val ? loc_val->first_column : 0); 188216fa7e82SJiri Olsa } 188316fa7e82SJiri Olsa 18846cee6cd3SArnaldo Carvalho de Melo int parse_events_term__sym_hw(struct parse_events_term **term, 18851d33d6dcSJiri Olsa char *config, unsigned idx) 18861d33d6dcSJiri Olsa { 18871d33d6dcSJiri Olsa struct event_symbol *sym; 18881d33d6dcSJiri Olsa 18891d33d6dcSJiri Olsa BUG_ON(idx >= PERF_COUNT_HW_MAX); 18901d33d6dcSJiri Olsa sym = &event_symbols_hw[idx]; 18911d33d6dcSJiri Olsa 18921d33d6dcSJiri Olsa if (config) 18931d33d6dcSJiri Olsa return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, 18941d33d6dcSJiri Olsa PARSE_EVENTS__TERM_TYPE_USER, config, 1895cecf3a2eSJiri Olsa (char *) sym->symbol, 0, 0, 0); 18961d33d6dcSJiri Olsa else 18971d33d6dcSJiri Olsa return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, 18981d33d6dcSJiri Olsa PARSE_EVENTS__TERM_TYPE_USER, 1899cecf3a2eSJiri Olsa (char *) "event", (char *) sym->symbol, 1900cecf3a2eSJiri Olsa 0, 0, 0); 19011d33d6dcSJiri Olsa } 19021d33d6dcSJiri Olsa 19036cee6cd3SArnaldo Carvalho de Melo int parse_events_term__clone(struct parse_events_term **new, 19046cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term) 1905a6146d50SZheng Yan { 1906a6146d50SZheng Yan return new_term(new, term->type_val, term->type_term, term->config, 1907cecf3a2eSJiri Olsa term->val.str, term->val.num, 1908cecf3a2eSJiri Olsa term->err_term, term->err_val); 1909a6146d50SZheng Yan } 1910a6146d50SZheng Yan 19118f707d84SJiri Olsa void parse_events__free_terms(struct list_head *terms) 19128f707d84SJiri Olsa { 19136cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term, *h; 19148f707d84SJiri Olsa 19158f707d84SJiri Olsa list_for_each_entry_safe(term, h, terms, list) 19168f707d84SJiri Olsa free(term); 19178f707d84SJiri Olsa } 1918b39b8393SJiri Olsa 1919b39b8393SJiri Olsa void parse_events_evlist_error(struct parse_events_evlist *data, 1920b39b8393SJiri Olsa int idx, const char *str) 1921b39b8393SJiri Olsa { 1922b39b8393SJiri Olsa struct parse_events_error *err = data->error; 1923b39b8393SJiri Olsa 1924a6ced2beSAdrian Hunter if (!err) 1925a6ced2beSAdrian Hunter return; 1926b39b8393SJiri Olsa err->idx = idx; 1927b39b8393SJiri Olsa err->str = strdup(str); 1928b39b8393SJiri Olsa WARN_ONCE(!err->str, "WARNING: failed to allocate error string"); 1929b39b8393SJiri Olsa } 1930ffeb883eSHe Kuang 1931ffeb883eSHe Kuang /* 1932ffeb883eSHe Kuang * Return string contains valid config terms of an event. 1933ffeb883eSHe Kuang * @additional_terms: For terms such as PMU sysfs terms. 1934ffeb883eSHe Kuang */ 1935ffeb883eSHe Kuang char *parse_events_formats_error_string(char *additional_terms) 1936ffeb883eSHe Kuang { 1937ffeb883eSHe Kuang char *str; 1938ffeb883eSHe Kuang static const char *static_terms = "config,config1,config2,name," 1939ffeb883eSHe Kuang "period,freq,branch_type,time," 1940ffeb883eSHe Kuang "call-graph,stack-size\n"; 1941ffeb883eSHe Kuang 1942ffeb883eSHe Kuang /* valid terms */ 1943ffeb883eSHe Kuang if (additional_terms) { 1944ffeb883eSHe Kuang if (!asprintf(&str, "valid terms: %s,%s", 1945ffeb883eSHe Kuang additional_terms, static_terms)) 1946ffeb883eSHe Kuang goto fail; 1947ffeb883eSHe Kuang } else { 1948ffeb883eSHe Kuang if (!asprintf(&str, "valid terms: %s", static_terms)) 1949ffeb883eSHe Kuang goto fail; 1950ffeb883eSHe Kuang } 1951ffeb883eSHe Kuang return str; 1952ffeb883eSHe Kuang 1953ffeb883eSHe Kuang fail: 1954ffeb883eSHe Kuang return NULL; 1955ffeb883eSHe Kuang } 1956