perf kvm: Move code to generate filename for perf-kvm to function.
[platform/adaptation/renesas_rcar/renesas_kernel.git] / tools / perf / util / util.c
1 #include "../perf.h"
2 #include "util.h"
3 #include <sys/mman.h>
4 #ifdef HAVE_BACKTRACE_SUPPORT
5 #include <execinfo.h>
6 #endif
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <errno.h>
11 #include <linux/kernel.h>
12
13 /*
14  * XXX We need to find a better place for these things...
15  */
16 unsigned int page_size;
17
18 bool test_attr__enabled;
19
20 bool perf_host  = true;
21 bool perf_guest = false;
22
23 char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";
24
25 void event_attr_init(struct perf_event_attr *attr)
26 {
27         if (!perf_host)
28                 attr->exclude_host  = 1;
29         if (!perf_guest)
30                 attr->exclude_guest = 1;
31         /* to capture ABI version */
32         attr->size = sizeof(*attr);
33 }
34
35 int mkdir_p(char *path, mode_t mode)
36 {
37         struct stat st;
38         int err;
39         char *d = path;
40
41         if (*d != '/')
42                 return -1;
43
44         if (stat(path, &st) == 0)
45                 return 0;
46
47         while (*++d == '/');
48
49         while ((d = strchr(d, '/'))) {
50                 *d = '\0';
51                 err = stat(path, &st) && mkdir(path, mode);
52                 *d++ = '/';
53                 if (err)
54                         return -1;
55                 while (*d == '/')
56                         ++d;
57         }
58         return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
59 }
60
61 static int slow_copyfile(const char *from, const char *to, mode_t mode)
62 {
63         int err = -1;
64         char *line = NULL;
65         size_t n;
66         FILE *from_fp = fopen(from, "r"), *to_fp;
67         mode_t old_umask;
68
69         if (from_fp == NULL)
70                 goto out;
71
72         old_umask = umask(mode ^ 0777);
73         to_fp = fopen(to, "w");
74         umask(old_umask);
75         if (to_fp == NULL)
76                 goto out_fclose_from;
77
78         while (getline(&line, &n, from_fp) > 0)
79                 if (fputs(line, to_fp) == EOF)
80                         goto out_fclose_to;
81         err = 0;
82 out_fclose_to:
83         fclose(to_fp);
84         free(line);
85 out_fclose_from:
86         fclose(from_fp);
87 out:
88         return err;
89 }
90
91 int copyfile_mode(const char *from, const char *to, mode_t mode)
92 {
93         int fromfd, tofd;
94         struct stat st;
95         void *addr;
96         int err = -1;
97
98         if (stat(from, &st))
99                 goto out;
100
101         if (st.st_size == 0) /* /proc? do it slowly... */
102                 return slow_copyfile(from, to, mode);
103
104         fromfd = open(from, O_RDONLY);
105         if (fromfd < 0)
106                 goto out;
107
108         tofd = creat(to, mode);
109         if (tofd < 0)
110                 goto out_close_from;
111
112         addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fromfd, 0);
113         if (addr == MAP_FAILED)
114                 goto out_close_to;
115
116         if (write(tofd, addr, st.st_size) == st.st_size)
117                 err = 0;
118
119         munmap(addr, st.st_size);
120 out_close_to:
121         close(tofd);
122         if (err)
123                 unlink(to);
124 out_close_from:
125         close(fromfd);
126 out:
127         return err;
128 }
129
130 int copyfile(const char *from, const char *to)
131 {
132         return copyfile_mode(from, to, 0755);
133 }
134
135 unsigned long convert_unit(unsigned long value, char *unit)
136 {
137         *unit = ' ';
138
139         if (value > 1000) {
140                 value /= 1000;
141                 *unit = 'K';
142         }
143
144         if (value > 1000) {
145                 value /= 1000;
146                 *unit = 'M';
147         }
148
149         if (value > 1000) {
150                 value /= 1000;
151                 *unit = 'G';
152         }
153
154         return value;
155 }
156
157 static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
158 {
159         void *buf_start = buf;
160         size_t left = n;
161
162         while (left) {
163                 ssize_t ret = is_read ? read(fd, buf, left) :
164                                         write(fd, buf, left);
165
166                 if (ret <= 0)
167                         return ret;
168
169                 left -= ret;
170                 buf  += ret;
171         }
172
173         BUG_ON((size_t)(buf - buf_start) != n);
174         return n;
175 }
176
177 /*
178  * Read exactly 'n' bytes or return an error.
179  */
180 ssize_t readn(int fd, void *buf, size_t n)
181 {
182         return ion(true, fd, buf, n);
183 }
184
185 /*
186  * Write exactly 'n' bytes or return an error.
187  */
188 ssize_t writen(int fd, void *buf, size_t n)
189 {
190         return ion(false, fd, buf, n);
191 }
192
193 size_t hex_width(u64 v)
194 {
195         size_t n = 1;
196
197         while ((v >>= 4))
198                 ++n;
199
200         return n;
201 }
202
203 static int hex(char ch)
204 {
205         if ((ch >= '0') && (ch <= '9'))
206                 return ch - '0';
207         if ((ch >= 'a') && (ch <= 'f'))
208                 return ch - 'a' + 10;
209         if ((ch >= 'A') && (ch <= 'F'))
210                 return ch - 'A' + 10;
211         return -1;
212 }
213
214 /*
215  * While we find nice hex chars, build a long_val.
216  * Return number of chars processed.
217  */
218 int hex2u64(const char *ptr, u64 *long_val)
219 {
220         const char *p = ptr;
221         *long_val = 0;
222
223         while (*p) {
224                 const int hex_val = hex(*p);
225
226                 if (hex_val < 0)
227                         break;
228
229                 *long_val = (*long_val << 4) | hex_val;
230                 p++;
231         }
232
233         return p - ptr;
234 }
235
236 /* Obtain a backtrace and print it to stdout. */
237 #ifdef HAVE_BACKTRACE_SUPPORT
238 void dump_stack(void)
239 {
240         void *array[16];
241         size_t size = backtrace(array, ARRAY_SIZE(array));
242         char **strings = backtrace_symbols(array, size);
243         size_t i;
244
245         printf("Obtained %zd stack frames.\n", size);
246
247         for (i = 0; i < size; i++)
248                 printf("%s\n", strings[i]);
249
250         free(strings);
251 }
252 #else
253 void dump_stack(void) {}
254 #endif
255
256 void get_term_dimensions(struct winsize *ws)
257 {
258         char *s = getenv("LINES");
259
260         if (s != NULL) {
261                 ws->ws_row = atoi(s);
262                 s = getenv("COLUMNS");
263                 if (s != NULL) {
264                         ws->ws_col = atoi(s);
265                         if (ws->ws_row && ws->ws_col)
266                                 return;
267                 }
268         }
269 #ifdef TIOCGWINSZ
270         if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
271             ws->ws_row && ws->ws_col)
272                 return;
273 #endif
274         ws->ws_row = 25;
275         ws->ws_col = 80;
276 }
277
278 static void set_tracing_events_path(const char *mountpoint)
279 {
280         snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
281                  mountpoint, "tracing/events");
282 }
283
284 const char *perf_debugfs_mount(const char *mountpoint)
285 {
286         const char *mnt;
287
288         mnt = debugfs_mount(mountpoint);
289         if (!mnt)
290                 return NULL;
291
292         set_tracing_events_path(mnt);
293
294         return mnt;
295 }
296
297 void perf_debugfs_set_path(const char *mntpt)
298 {
299         snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt);
300         set_tracing_events_path(mntpt);
301 }
302
303 static const char *find_debugfs(void)
304 {
305         const char *path = perf_debugfs_mount(NULL);
306
307         if (!path)
308                 fprintf(stderr, "Your kernel does not support the debugfs filesystem");
309
310         return path;
311 }
312
313 /*
314  * Finds the path to the debugfs/tracing
315  * Allocates the string and stores it.
316  */
317 const char *find_tracing_dir(void)
318 {
319         static char *tracing;
320         static int tracing_found;
321         const char *debugfs;
322
323         if (tracing_found)
324                 return tracing;
325
326         debugfs = find_debugfs();
327         if (!debugfs)
328                 return NULL;
329
330         tracing = malloc(strlen(debugfs) + 9);
331         if (!tracing)
332                 return NULL;
333
334         sprintf(tracing, "%s/tracing", debugfs);
335
336         tracing_found = 1;
337         return tracing;
338 }
339
340 char *get_tracing_file(const char *name)
341 {
342         const char *tracing;
343         char *file;
344
345         tracing = find_tracing_dir();
346         if (!tracing)
347                 return NULL;
348
349         file = malloc(strlen(tracing) + strlen(name) + 2);
350         if (!file)
351                 return NULL;
352
353         sprintf(file, "%s/%s", tracing, name);
354         return file;
355 }
356
357 void put_tracing_file(char *file)
358 {
359         free(file);
360 }
361
362 int parse_nsec_time(const char *str, u64 *ptime)
363 {
364         u64 time_sec, time_nsec;
365         char *end;
366
367         time_sec = strtoul(str, &end, 10);
368         if (*end != '.' && *end != '\0')
369                 return -1;
370
371         if (*end == '.') {
372                 int i;
373                 char nsec_buf[10];
374
375                 if (strlen(++end) > 9)
376                         return -1;
377
378                 strncpy(nsec_buf, end, 9);
379                 nsec_buf[9] = '\0';
380
381                 /* make it nsec precision */
382                 for (i = strlen(nsec_buf); i < 9; i++)
383                         nsec_buf[i] = '0';
384
385                 time_nsec = strtoul(nsec_buf, &end, 10);
386                 if (*end != '\0')
387                         return -1;
388         } else
389                 time_nsec = 0;
390
391         *ptime = time_sec * NSEC_PER_SEC + time_nsec;
392         return 0;
393 }
394
395 unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
396 {
397         struct parse_tag *i = tags;
398
399         while (i->tag) {
400                 char *s;
401
402                 s = strchr(str, i->tag);
403                 if (s) {
404                         unsigned long int value;
405                         char *endptr;
406
407                         value = strtoul(str, &endptr, 10);
408                         if (s != endptr)
409                                 break;
410
411                         if (value > ULONG_MAX / i->mult)
412                                 break;
413                         value *= i->mult;
414                         return value;
415                 }
416                 i++;
417         }
418
419         return (unsigned long) -1;
420 }
421
422 int filename__read_int(const char *filename, int *value)
423 {
424         char line[64];
425         int fd = open(filename, O_RDONLY), err = -1;
426
427         if (fd < 0)
428                 return -1;
429
430         if (read(fd, line, sizeof(line)) > 0) {
431                 *value = atoi(line);
432                 err = 0;
433         }
434
435         close(fd);
436         return err;
437 }
438
439 int filename__read_str(const char *filename, char **buf, size_t *sizep)
440 {
441         size_t size = 0, alloc_size = 0;
442         void *bf = NULL, *nbf;
443         int fd, n, err = 0;
444
445         fd = open(filename, O_RDONLY);
446         if (fd < 0)
447                 return -errno;
448
449         do {
450                 if (size == alloc_size) {
451                         alloc_size += BUFSIZ;
452                         nbf = realloc(bf, alloc_size);
453                         if (!nbf) {
454                                 err = -ENOMEM;
455                                 break;
456                         }
457
458                         bf = nbf;
459                 }
460
461                 n = read(fd, bf + size, alloc_size - size);
462                 if (n < 0) {
463                         if (size) {
464                                 pr_warning("read failed %d: %s\n",
465                                            errno, strerror(errno));
466                                 err = 0;
467                         } else
468                                 err = -errno;
469
470                         break;
471                 }
472
473                 size += n;
474         } while (n > 0);
475
476         if (!err) {
477                 *sizep = size;
478                 *buf   = bf;
479         } else
480                 free(bf);
481
482         close(fd);
483         return err;
484 }
485
486 const char *get_filename_for_perf_kvm(void)
487 {
488         const char *filename;
489
490         if (perf_host && !perf_guest)
491                 filename = strdup("perf.data.host");
492         else if (!perf_host && perf_guest)
493                 filename = strdup("perf.data.guest");
494         else
495                 filename = strdup("perf.data.kvm");
496
497         return filename;
498 }