1faf96706SAdrian Hunter #include "evlist.h" 2faf96706SAdrian Hunter #include "evsel.h" 3faf96706SAdrian Hunter #include "cpumap.h" 475562573SAdrian Hunter #include "parse-events.h" 5cd0cfad7SBorislav Petkov #include <api/fs/fs.h> 6714647bdSJiri Olsa #include "util.h" 757480d2cSYann Droneaud #include "cloexec.h" 875562573SAdrian Hunter 975562573SAdrian Hunter typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel); 1075562573SAdrian Hunter 1175562573SAdrian Hunter static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str) 1275562573SAdrian Hunter { 1375562573SAdrian Hunter struct perf_evlist *evlist; 1475562573SAdrian Hunter struct perf_evsel *evsel; 1557480d2cSYann Droneaud unsigned long flags = perf_event_open_cloexec_flag(); 1675562573SAdrian Hunter int err = -EAGAIN, fd; 1746ec69adSAdrian Hunter static pid_t pid = -1; 1875562573SAdrian Hunter 1975562573SAdrian Hunter evlist = perf_evlist__new(); 2075562573SAdrian Hunter if (!evlist) 2175562573SAdrian Hunter return -ENOMEM; 2275562573SAdrian Hunter 23*b39b8393SJiri Olsa if (parse_events(evlist, str, NULL)) 2475562573SAdrian Hunter goto out_delete; 2575562573SAdrian Hunter 2675562573SAdrian Hunter evsel = perf_evlist__first(evlist); 2775562573SAdrian Hunter 2846ec69adSAdrian Hunter while (1) { 2946ec69adSAdrian Hunter fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags); 3046ec69adSAdrian Hunter if (fd < 0) { 3146ec69adSAdrian Hunter if (pid == -1 && errno == EACCES) { 3246ec69adSAdrian Hunter pid = 0; 3346ec69adSAdrian Hunter continue; 3446ec69adSAdrian Hunter } 3575562573SAdrian Hunter goto out_delete; 3646ec69adSAdrian Hunter } 3746ec69adSAdrian Hunter break; 3846ec69adSAdrian Hunter } 3975562573SAdrian Hunter close(fd); 4075562573SAdrian Hunter 4175562573SAdrian Hunter fn(evsel); 4275562573SAdrian Hunter 4346ec69adSAdrian Hunter fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags); 4475562573SAdrian Hunter if (fd < 0) { 4575562573SAdrian Hunter if (errno == EINVAL) 4675562573SAdrian Hunter err = -EINVAL; 4775562573SAdrian Hunter goto out_delete; 4875562573SAdrian Hunter } 4975562573SAdrian Hunter close(fd); 5075562573SAdrian Hunter err = 0; 5175562573SAdrian Hunter 5275562573SAdrian Hunter out_delete: 5375562573SAdrian Hunter perf_evlist__delete(evlist); 5475562573SAdrian Hunter return err; 5575562573SAdrian Hunter } 5675562573SAdrian Hunter 5775562573SAdrian Hunter static bool perf_probe_api(setup_probe_fn_t fn) 5875562573SAdrian Hunter { 59c6fa3565SAdrian Hunter const char *try[] = {"cycles:u", "instructions:u", "cpu-clock:u", NULL}; 6075562573SAdrian Hunter struct cpu_map *cpus; 6175562573SAdrian Hunter int cpu, ret, i = 0; 6275562573SAdrian Hunter 6375562573SAdrian Hunter cpus = cpu_map__new(NULL); 6475562573SAdrian Hunter if (!cpus) 6575562573SAdrian Hunter return false; 6675562573SAdrian Hunter cpu = cpus->map[0]; 6775562573SAdrian Hunter cpu_map__delete(cpus); 6875562573SAdrian Hunter 6975562573SAdrian Hunter do { 7075562573SAdrian Hunter ret = perf_do_probe_api(fn, cpu, try[i++]); 7175562573SAdrian Hunter if (!ret) 7275562573SAdrian Hunter return true; 7375562573SAdrian Hunter } while (ret == -EAGAIN && try[i]); 7475562573SAdrian Hunter 7575562573SAdrian Hunter return false; 7675562573SAdrian Hunter } 7775562573SAdrian Hunter 7875562573SAdrian Hunter static void perf_probe_sample_identifier(struct perf_evsel *evsel) 7975562573SAdrian Hunter { 8075562573SAdrian Hunter evsel->attr.sample_type |= PERF_SAMPLE_IDENTIFIER; 8175562573SAdrian Hunter } 8275562573SAdrian Hunter 8339e09d40SAdrian Hunter static void perf_probe_comm_exec(struct perf_evsel *evsel) 8439e09d40SAdrian Hunter { 8539e09d40SAdrian Hunter evsel->attr.comm_exec = 1; 8639e09d40SAdrian Hunter } 8739e09d40SAdrian Hunter 8875562573SAdrian Hunter bool perf_can_sample_identifier(void) 8975562573SAdrian Hunter { 9075562573SAdrian Hunter return perf_probe_api(perf_probe_sample_identifier); 9175562573SAdrian Hunter } 92faf96706SAdrian Hunter 9339e09d40SAdrian Hunter static bool perf_can_comm_exec(void) 9439e09d40SAdrian Hunter { 9539e09d40SAdrian Hunter return perf_probe_api(perf_probe_comm_exec); 9639e09d40SAdrian Hunter } 9739e09d40SAdrian Hunter 98b4006796SArnaldo Carvalho de Melo void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts) 99faf96706SAdrian Hunter { 100faf96706SAdrian Hunter struct perf_evsel *evsel; 10175562573SAdrian Hunter bool use_sample_identifier = false; 10239e09d40SAdrian Hunter bool use_comm_exec; 10375562573SAdrian Hunter 104faf96706SAdrian Hunter /* 105faf96706SAdrian Hunter * Set the evsel leader links before we configure attributes, 106faf96706SAdrian Hunter * since some might depend on this info. 107faf96706SAdrian Hunter */ 108faf96706SAdrian Hunter if (opts->group) 109faf96706SAdrian Hunter perf_evlist__set_leader(evlist); 110faf96706SAdrian Hunter 111faf96706SAdrian Hunter if (evlist->cpus->map[0] < 0) 112faf96706SAdrian Hunter opts->no_inherit = true; 113faf96706SAdrian Hunter 11439e09d40SAdrian Hunter use_comm_exec = perf_can_comm_exec(); 11539e09d40SAdrian Hunter 11639e09d40SAdrian Hunter evlist__for_each(evlist, evsel) { 117faf96706SAdrian Hunter perf_evsel__config(evsel, opts); 11860b0896cSAdrian Hunter if (evsel->tracking && use_comm_exec) 11939e09d40SAdrian Hunter evsel->attr.comm_exec = 1; 12039e09d40SAdrian Hunter } 121faf96706SAdrian Hunter 1229e0cc4feSAdrian Hunter if (opts->full_auxtrace) { 1239e0cc4feSAdrian Hunter /* 1249e0cc4feSAdrian Hunter * Need to be able to synthesize and parse selected events with 1259e0cc4feSAdrian Hunter * arbitrary sample types, which requires always being able to 1269e0cc4feSAdrian Hunter * match the id. 1279e0cc4feSAdrian Hunter */ 1289e0cc4feSAdrian Hunter use_sample_identifier = perf_can_sample_identifier(); 1299e0cc4feSAdrian Hunter evlist__for_each(evlist, evsel) 1309e0cc4feSAdrian Hunter perf_evsel__set_sample_id(evsel, use_sample_identifier); 1319e0cc4feSAdrian Hunter } else if (evlist->nr_entries > 1) { 13275562573SAdrian Hunter struct perf_evsel *first = perf_evlist__first(evlist); 13375562573SAdrian Hunter 1340050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, evsel) { 13575562573SAdrian Hunter if (evsel->attr.sample_type == first->attr.sample_type) 13675562573SAdrian Hunter continue; 13775562573SAdrian Hunter use_sample_identifier = perf_can_sample_identifier(); 13875562573SAdrian Hunter break; 139faf96706SAdrian Hunter } 1400050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, evsel) 14175562573SAdrian Hunter perf_evsel__set_sample_id(evsel, use_sample_identifier); 14275562573SAdrian Hunter } 14375562573SAdrian Hunter 14475562573SAdrian Hunter perf_evlist__set_id_pos(evlist); 145faf96706SAdrian Hunter } 146714647bdSJiri Olsa 147714647bdSJiri Olsa static int get_max_rate(unsigned int *rate) 148714647bdSJiri Olsa { 149ce27309fSArnaldo Carvalho de Melo return sysctl__read_int("kernel/perf_event_max_sample_rate", (int *)rate); 150714647bdSJiri Olsa } 151714647bdSJiri Olsa 152b4006796SArnaldo Carvalho de Melo static int record_opts__config_freq(struct record_opts *opts) 153714647bdSJiri Olsa { 154714647bdSJiri Olsa bool user_freq = opts->user_freq != UINT_MAX; 155714647bdSJiri Olsa unsigned int max_rate; 156714647bdSJiri Olsa 157714647bdSJiri Olsa if (opts->user_interval != ULLONG_MAX) 158714647bdSJiri Olsa opts->default_interval = opts->user_interval; 159714647bdSJiri Olsa if (user_freq) 160714647bdSJiri Olsa opts->freq = opts->user_freq; 161714647bdSJiri Olsa 162714647bdSJiri Olsa /* 163714647bdSJiri Olsa * User specified count overrides default frequency. 164714647bdSJiri Olsa */ 165714647bdSJiri Olsa if (opts->default_interval) 166714647bdSJiri Olsa opts->freq = 0; 167714647bdSJiri Olsa else if (opts->freq) { 168714647bdSJiri Olsa opts->default_interval = opts->freq; 169714647bdSJiri Olsa } else { 170714647bdSJiri Olsa pr_err("frequency and count are zero, aborting\n"); 171714647bdSJiri Olsa return -1; 172714647bdSJiri Olsa } 173714647bdSJiri Olsa 174714647bdSJiri Olsa if (get_max_rate(&max_rate)) 175714647bdSJiri Olsa return 0; 176714647bdSJiri Olsa 177714647bdSJiri Olsa /* 178714647bdSJiri Olsa * User specified frequency is over current maximum. 179714647bdSJiri Olsa */ 180714647bdSJiri Olsa if (user_freq && (max_rate < opts->freq)) { 181714647bdSJiri Olsa pr_err("Maximum frequency rate (%u) reached.\n" 182714647bdSJiri Olsa "Please use -F freq option with lower value or consider\n" 183714647bdSJiri Olsa "tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n", 184714647bdSJiri Olsa max_rate); 185714647bdSJiri Olsa return -1; 186714647bdSJiri Olsa } 187714647bdSJiri Olsa 188714647bdSJiri Olsa /* 189714647bdSJiri Olsa * Default frequency is over current maximum. 190714647bdSJiri Olsa */ 191714647bdSJiri Olsa if (max_rate < opts->freq) { 192714647bdSJiri Olsa pr_warning("Lowering default frequency rate to %u.\n" 193714647bdSJiri Olsa "Please consider tweaking " 194714647bdSJiri Olsa "/proc/sys/kernel/perf_event_max_sample_rate.\n", 195714647bdSJiri Olsa max_rate); 196714647bdSJiri Olsa opts->freq = max_rate; 197714647bdSJiri Olsa } 198714647bdSJiri Olsa 199714647bdSJiri Olsa return 0; 200714647bdSJiri Olsa } 201714647bdSJiri Olsa 202b4006796SArnaldo Carvalho de Melo int record_opts__config(struct record_opts *opts) 203714647bdSJiri Olsa { 204b4006796SArnaldo Carvalho de Melo return record_opts__config_freq(opts); 205714647bdSJiri Olsa } 206c09ec622SAdrian Hunter 207c09ec622SAdrian Hunter bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str) 208c09ec622SAdrian Hunter { 209c09ec622SAdrian Hunter struct perf_evlist *temp_evlist; 210c09ec622SAdrian Hunter struct perf_evsel *evsel; 211c09ec622SAdrian Hunter int err, fd, cpu; 212c09ec622SAdrian Hunter bool ret = false; 21346ec69adSAdrian Hunter pid_t pid = -1; 214c09ec622SAdrian Hunter 215c09ec622SAdrian Hunter temp_evlist = perf_evlist__new(); 216c09ec622SAdrian Hunter if (!temp_evlist) 217c09ec622SAdrian Hunter return false; 218c09ec622SAdrian Hunter 219*b39b8393SJiri Olsa err = parse_events(temp_evlist, str, NULL); 220c09ec622SAdrian Hunter if (err) 221c09ec622SAdrian Hunter goto out_delete; 222c09ec622SAdrian Hunter 223c09ec622SAdrian Hunter evsel = perf_evlist__last(temp_evlist); 224c09ec622SAdrian Hunter 225c09ec622SAdrian Hunter if (!evlist || cpu_map__empty(evlist->cpus)) { 226c09ec622SAdrian Hunter struct cpu_map *cpus = cpu_map__new(NULL); 227c09ec622SAdrian Hunter 228c09ec622SAdrian Hunter cpu = cpus ? cpus->map[0] : 0; 229c09ec622SAdrian Hunter cpu_map__delete(cpus); 230c09ec622SAdrian Hunter } else { 231c09ec622SAdrian Hunter cpu = evlist->cpus->map[0]; 232c09ec622SAdrian Hunter } 233c09ec622SAdrian Hunter 23446ec69adSAdrian Hunter while (1) { 23546ec69adSAdrian Hunter fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, 23657480d2cSYann Droneaud perf_event_open_cloexec_flag()); 23746ec69adSAdrian Hunter if (fd < 0) { 23846ec69adSAdrian Hunter if (pid == -1 && errno == EACCES) { 23946ec69adSAdrian Hunter pid = 0; 24046ec69adSAdrian Hunter continue; 24146ec69adSAdrian Hunter } 24246ec69adSAdrian Hunter goto out_delete; 24346ec69adSAdrian Hunter } 24446ec69adSAdrian Hunter break; 24546ec69adSAdrian Hunter } 246c09ec622SAdrian Hunter close(fd); 247c09ec622SAdrian Hunter ret = true; 248c09ec622SAdrian Hunter 249c09ec622SAdrian Hunter out_delete: 250c09ec622SAdrian Hunter perf_evlist__delete(temp_evlist); 251c09ec622SAdrian Hunter return ret; 252c09ec622SAdrian Hunter } 253