1 #include "evlist.h" 2 #include "evsel.h" 3 #include "cpumap.h" 4 #include "parse-events.h" 5 #include <api/fs/fs.h> 6 #include "util.h" 7 #include "cloexec.h" 8 9 typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel); 10 11 static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str) 12 { 13 struct perf_evlist *evlist; 14 struct perf_evsel *evsel; 15 unsigned long flags = perf_event_open_cloexec_flag(); 16 int err = -EAGAIN, fd; 17 static pid_t pid = -1; 18 19 evlist = perf_evlist__new(); 20 if (!evlist) 21 return -ENOMEM; 22 23 if (parse_events(evlist, str, NULL)) 24 goto out_delete; 25 26 evsel = perf_evlist__first(evlist); 27 28 while (1) { 29 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags); 30 if (fd < 0) { 31 if (pid == -1 && errno == EACCES) { 32 pid = 0; 33 continue; 34 } 35 goto out_delete; 36 } 37 break; 38 } 39 close(fd); 40 41 fn(evsel); 42 43 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags); 44 if (fd < 0) { 45 if (errno == EINVAL) 46 err = -EINVAL; 47 goto out_delete; 48 } 49 close(fd); 50 err = 0; 51 52 out_delete: 53 perf_evlist__delete(evlist); 54 return err; 55 } 56 57 static bool perf_probe_api(setup_probe_fn_t fn) 58 { 59 const char *try[] = {"cycles:u", "instructions:u", "cpu-clock:u", NULL}; 60 struct cpu_map *cpus; 61 int cpu, ret, i = 0; 62 63 cpus = cpu_map__new(NULL); 64 if (!cpus) 65 return false; 66 cpu = cpus->map[0]; 67 cpu_map__put(cpus); 68 69 do { 70 ret = perf_do_probe_api(fn, cpu, try[i++]); 71 if (!ret) 72 return true; 73 } while (ret == -EAGAIN && try[i]); 74 75 return false; 76 } 77 78 static void perf_probe_sample_identifier(struct perf_evsel *evsel) 79 { 80 evsel->attr.sample_type |= PERF_SAMPLE_IDENTIFIER; 81 } 82 83 static void perf_probe_comm_exec(struct perf_evsel *evsel) 84 { 85 evsel->attr.comm_exec = 1; 86 } 87 88 bool perf_can_sample_identifier(void) 89 { 90 return perf_probe_api(perf_probe_sample_identifier); 91 } 92 93 static bool perf_can_comm_exec(void) 94 { 95 return perf_probe_api(perf_probe_comm_exec); 96 } 97 98 void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts) 99 { 100 struct perf_evsel *evsel; 101 bool use_sample_identifier = false; 102 bool use_comm_exec; 103 104 /* 105 * Set the evsel leader links before we configure attributes, 106 * since some might depend on this info. 107 */ 108 if (opts->group) 109 perf_evlist__set_leader(evlist); 110 111 if (evlist->cpus->map[0] < 0) 112 opts->no_inherit = true; 113 114 use_comm_exec = perf_can_comm_exec(); 115 116 evlist__for_each(evlist, evsel) { 117 perf_evsel__config(evsel, opts); 118 if (evsel->tracking && use_comm_exec) 119 evsel->attr.comm_exec = 1; 120 } 121 122 if (opts->full_auxtrace) { 123 /* 124 * Need to be able to synthesize and parse selected events with 125 * arbitrary sample types, which requires always being able to 126 * match the id. 127 */ 128 use_sample_identifier = perf_can_sample_identifier(); 129 evlist__for_each(evlist, evsel) 130 perf_evsel__set_sample_id(evsel, use_sample_identifier); 131 } else if (evlist->nr_entries > 1) { 132 struct perf_evsel *first = perf_evlist__first(evlist); 133 134 evlist__for_each(evlist, evsel) { 135 if (evsel->attr.sample_type == first->attr.sample_type) 136 continue; 137 use_sample_identifier = perf_can_sample_identifier(); 138 break; 139 } 140 evlist__for_each(evlist, evsel) 141 perf_evsel__set_sample_id(evsel, use_sample_identifier); 142 } 143 144 perf_evlist__set_id_pos(evlist); 145 } 146 147 static int get_max_rate(unsigned int *rate) 148 { 149 return sysctl__read_int("kernel/perf_event_max_sample_rate", (int *)rate); 150 } 151 152 static int record_opts__config_freq(struct record_opts *opts) 153 { 154 bool user_freq = opts->user_freq != UINT_MAX; 155 unsigned int max_rate; 156 157 if (opts->user_interval != ULLONG_MAX) 158 opts->default_interval = opts->user_interval; 159 if (user_freq) 160 opts->freq = opts->user_freq; 161 162 /* 163 * User specified count overrides default frequency. 164 */ 165 if (opts->default_interval) 166 opts->freq = 0; 167 else if (opts->freq) { 168 opts->default_interval = opts->freq; 169 } else { 170 pr_err("frequency and count are zero, aborting\n"); 171 return -1; 172 } 173 174 if (get_max_rate(&max_rate)) 175 return 0; 176 177 /* 178 * User specified frequency is over current maximum. 179 */ 180 if (user_freq && (max_rate < opts->freq)) { 181 pr_err("Maximum frequency rate (%u) reached.\n" 182 "Please use -F freq option with lower value or consider\n" 183 "tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n", 184 max_rate); 185 return -1; 186 } 187 188 /* 189 * Default frequency is over current maximum. 190 */ 191 if (max_rate < opts->freq) { 192 pr_warning("Lowering default frequency rate to %u.\n" 193 "Please consider tweaking " 194 "/proc/sys/kernel/perf_event_max_sample_rate.\n", 195 max_rate); 196 opts->freq = max_rate; 197 } 198 199 return 0; 200 } 201 202 int record_opts__config(struct record_opts *opts) 203 { 204 return record_opts__config_freq(opts); 205 } 206 207 bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str) 208 { 209 struct perf_evlist *temp_evlist; 210 struct perf_evsel *evsel; 211 int err, fd, cpu; 212 bool ret = false; 213 pid_t pid = -1; 214 215 temp_evlist = perf_evlist__new(); 216 if (!temp_evlist) 217 return false; 218 219 err = parse_events(temp_evlist, str, NULL); 220 if (err) 221 goto out_delete; 222 223 evsel = perf_evlist__last(temp_evlist); 224 225 if (!evlist || cpu_map__empty(evlist->cpus)) { 226 struct cpu_map *cpus = cpu_map__new(NULL); 227 228 cpu = cpus ? cpus->map[0] : 0; 229 cpu_map__put(cpus); 230 } else { 231 cpu = evlist->cpus->map[0]; 232 } 233 234 while (1) { 235 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, 236 perf_event_open_cloexec_flag()); 237 if (fd < 0) { 238 if (pid == -1 && errno == EACCES) { 239 pid = 0; 240 continue; 241 } 242 goto out_delete; 243 } 244 break; 245 } 246 close(fd); 247 ret = true; 248 249 out_delete: 250 perf_evlist__delete(temp_evlist); 251 return ret; 252 } 253