xref: /openbmc/qemu/trace/ftrace.c (revision 1abdde1ad42d0ebccc5e8bc574ebe805cd650102)
1 /*
2  * Ftrace trace backend
3  *
4  * Copyright (C) 2013 Hitachi, Ltd.
5  * Created by Eiichi Tsukata <eiichi.tsukata.xh@hitachi.com>
6  *
7  * This work is licensed under the terms of the GNU GPL, version 2.  See
8  * the COPYING file in the top-level directory.
9  *
10  */
11 
12 #include "qemu/osdep.h"
13 #include "trace/control.h"
14 #include "trace/ftrace.h"
15 
16 int trace_marker_fd;
17 
18 static int find_mount(char *mount_point, const char *fstype)
19 {
20     char type[100];
21     FILE *fp;
22     int ret = 0;
23 
24     fp = fopen("/proc/mounts", "r");
25     if (fp == NULL) {
26         return 0;
27     }
28 
29     while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
30                   mount_point, type) == 2) {
31         if (strcmp(type, fstype) == 0) {
32             ret = 1;
33             break;
34         }
35     }
36     fclose(fp);
37 
38     return ret;
39 }
40 
41 void ftrace_write(const char *fmt, ...)
42 {
43     char ftrace_buf[MAX_TRACE_STRLEN];
44     int unused __attribute__ ((unused));
45     int trlen;
46     va_list ap;
47 
48     va_start(ap, fmt);
49     trlen = vsnprintf(ftrace_buf, MAX_TRACE_STRLEN, fmt, ap);
50     va_end(ap);
51 
52     trlen = MIN(trlen, MAX_TRACE_STRLEN - 1);
53     unused = write(trace_marker_fd, ftrace_buf, trlen);
54 }
55 
56 bool ftrace_init(void)
57 {
58     char mount_point[PATH_MAX];
59     char path[PATH_MAX];
60     int tracefs_found;
61     int trace_fd = -1;
62     const char *subdir = "";
63 
64     tracefs_found = find_mount(mount_point, "tracefs");
65     if (!tracefs_found) {
66         tracefs_found = find_mount(mount_point, "debugfs");
67         subdir = "/tracing";
68     }
69 
70     if (tracefs_found) {
71         if (snprintf(path, PATH_MAX, "%s%s/tracing_on", mount_point, subdir)
72                 >= sizeof(path)) {
73             fprintf(stderr, "Using tracefs mountpoint would exceed PATH_MAX\n");
74             return false;
75         }
76         trace_fd = open(path, O_WRONLY);
77         if (trace_fd < 0) {
78             if (errno == EACCES) {
79                 trace_marker_fd = open("/dev/null", O_WRONLY);
80                 if (trace_marker_fd != -1) {
81                     return true;
82                 }
83             }
84             perror("Could not open ftrace 'tracing_on' file");
85             return false;
86         } else {
87             if (write(trace_fd, "1", 1) < 0) {
88                 perror("Could not write to 'tracing_on' file");
89                 close(trace_fd);
90                 return false;
91             }
92             close(trace_fd);
93         }
94         if (snprintf(path, PATH_MAX, "%s%s/trace_marker", mount_point, subdir)
95                 >= sizeof(path)) {
96             fprintf(stderr, "Using tracefs mountpoint would exceed PATH_MAX\n");
97             return false;
98         }
99         trace_marker_fd = open(path, O_WRONLY);
100         if (trace_marker_fd < 0) {
101             perror("Could not open ftrace 'trace_marker' file");
102             return false;
103         }
104     } else {
105         fprintf(stderr, "tracefs is not mounted\n");
106         return false;
107     }
108 
109     return true;
110 }
111