Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[firefly-linux-kernel-4.4.55.git] / tools / perf / util / record.c
1 #include "evlist.h"
2 #include "evsel.h"
3 #include "cpumap.h"
4 #include "parse-events.h"
5 #include "fs.h"
6 #include "util.h"
7
8 typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel);
9
10 static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
11 {
12         struct perf_evlist *evlist;
13         struct perf_evsel *evsel;
14         int err = -EAGAIN, fd;
15
16         evlist = perf_evlist__new();
17         if (!evlist)
18                 return -ENOMEM;
19
20         if (parse_events(evlist, str))
21                 goto out_delete;
22
23         evsel = perf_evlist__first(evlist);
24
25         fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0);
26         if (fd < 0)
27                 goto out_delete;
28         close(fd);
29
30         fn(evsel);
31
32         fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0);
33         if (fd < 0) {
34                 if (errno == EINVAL)
35                         err = -EINVAL;
36                 goto out_delete;
37         }
38         close(fd);
39         err = 0;
40
41 out_delete:
42         perf_evlist__delete(evlist);
43         return err;
44 }
45
46 static bool perf_probe_api(setup_probe_fn_t fn)
47 {
48         const char *try[] = {"cycles:u", "instructions:u", "cpu-clock", NULL};
49         struct cpu_map *cpus;
50         int cpu, ret, i = 0;
51
52         cpus = cpu_map__new(NULL);
53         if (!cpus)
54                 return false;
55         cpu = cpus->map[0];
56         cpu_map__delete(cpus);
57
58         do {
59                 ret = perf_do_probe_api(fn, cpu, try[i++]);
60                 if (!ret)
61                         return true;
62         } while (ret == -EAGAIN && try[i]);
63
64         return false;
65 }
66
67 static void perf_probe_sample_identifier(struct perf_evsel *evsel)
68 {
69         evsel->attr.sample_type |= PERF_SAMPLE_IDENTIFIER;
70 }
71
72 bool perf_can_sample_identifier(void)
73 {
74         return perf_probe_api(perf_probe_sample_identifier);
75 }
76
77 void perf_evlist__config(struct perf_evlist *evlist,
78                         struct perf_record_opts *opts)
79 {
80         struct perf_evsel *evsel;
81         bool use_sample_identifier = false;
82
83         /*
84          * Set the evsel leader links before we configure attributes,
85          * since some might depend on this info.
86          */
87         if (opts->group)
88                 perf_evlist__set_leader(evlist);
89
90         if (evlist->cpus->map[0] < 0)
91                 opts->no_inherit = true;
92
93         list_for_each_entry(evsel, &evlist->entries, node)
94                 perf_evsel__config(evsel, opts);
95
96         if (evlist->nr_entries > 1) {
97                 struct perf_evsel *first = perf_evlist__first(evlist);
98
99                 list_for_each_entry(evsel, &evlist->entries, node) {
100                         if (evsel->attr.sample_type == first->attr.sample_type)
101                                 continue;
102                         use_sample_identifier = perf_can_sample_identifier();
103                         break;
104                 }
105                 list_for_each_entry(evsel, &evlist->entries, node)
106                         perf_evsel__set_sample_id(evsel, use_sample_identifier);
107         }
108
109         perf_evlist__set_id_pos(evlist);
110 }
111
112 static int get_max_rate(unsigned int *rate)
113 {
114         char path[PATH_MAX];
115         const char *procfs = procfs__mountpoint();
116
117         if (!procfs)
118                 return -1;
119
120         snprintf(path, PATH_MAX,
121                  "%s/sys/kernel/perf_event_max_sample_rate", procfs);
122
123         return filename__read_int(path, (int *) rate);
124 }
125
126 static int perf_record_opts__config_freq(struct perf_record_opts *opts)
127 {
128         bool user_freq = opts->user_freq != UINT_MAX;
129         unsigned int max_rate;
130
131         if (opts->user_interval != ULLONG_MAX)
132                 opts->default_interval = opts->user_interval;
133         if (user_freq)
134                 opts->freq = opts->user_freq;
135
136         /*
137          * User specified count overrides default frequency.
138          */
139         if (opts->default_interval)
140                 opts->freq = 0;
141         else if (opts->freq) {
142                 opts->default_interval = opts->freq;
143         } else {
144                 pr_err("frequency and count are zero, aborting\n");
145                 return -1;
146         }
147
148         if (get_max_rate(&max_rate))
149                 return 0;
150
151         /*
152          * User specified frequency is over current maximum.
153          */
154         if (user_freq && (max_rate < opts->freq)) {
155                 pr_err("Maximum frequency rate (%u) reached.\n"
156                    "Please use -F freq option with lower value or consider\n"
157                    "tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n",
158                    max_rate);
159                 return -1;
160         }
161
162         /*
163          * Default frequency is over current maximum.
164          */
165         if (max_rate < opts->freq) {
166                 pr_warning("Lowering default frequency rate to %u.\n"
167                            "Please consider tweaking "
168                            "/proc/sys/kernel/perf_event_max_sample_rate.\n",
169                            max_rate);
170                 opts->freq = max_rate;
171         }
172
173         return 0;
174 }
175
176 int perf_record_opts__config(struct perf_record_opts *opts)
177 {
178         return perf_record_opts__config_freq(opts);
179 }