]>
Commit | Line | Data |
---|---|---|
7aef3bf3 JO |
1 | #include <linux/compiler.h> |
2 | #include <linux/kernel.h> | |
3 | #include "util.h" | |
4 | #include "debug.h" | |
5 | #include "builtin.h" | |
6 | #include <subcmd/parse-options.h> | |
39bcd4a4 | 7 | #include "mem-events.h" |
903a6f15 JO |
8 | #include "session.h" |
9 | #include "hist.h" | |
10 | #include "tool.h" | |
11 | #include "data.h" | |
12 | ||
13 | struct perf_c2c { | |
14 | struct perf_tool tool; | |
15 | }; | |
16 | ||
17 | static struct perf_c2c c2c; | |
7aef3bf3 JO |
18 | |
19 | static const char * const c2c_usage[] = { | |
903a6f15 | 20 | "perf c2c {record|report}", |
7aef3bf3 JO |
21 | NULL |
22 | }; | |
23 | ||
903a6f15 JO |
24 | static const char * const __usage_report[] = { |
25 | "perf c2c report", | |
26 | NULL | |
27 | }; | |
28 | ||
29 | static const char * const *report_c2c_usage = __usage_report; | |
30 | ||
31 | static int perf_c2c__report(int argc, const char **argv) | |
32 | { | |
33 | struct perf_session *session; | |
34 | struct perf_data_file file = { | |
35 | .mode = PERF_DATA_MODE_READ, | |
36 | }; | |
37 | const struct option c2c_options[] = { | |
38 | OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, | |
39 | "file", "vmlinux pathname"), | |
40 | OPT_INCR('v', "verbose", &verbose, | |
41 | "be more verbose (show counter open errors, etc)"), | |
42 | OPT_STRING('i', "input", &input_name, "file", | |
43 | "the input file to process"), | |
44 | OPT_END() | |
45 | }; | |
46 | int err = 0; | |
47 | ||
48 | argc = parse_options(argc, argv, c2c_options, report_c2c_usage, | |
49 | PARSE_OPT_STOP_AT_NON_OPTION); | |
50 | if (!argc) | |
51 | usage_with_options(report_c2c_usage, c2c_options); | |
52 | ||
53 | file.path = input_name; | |
54 | ||
55 | session = perf_session__new(&file, 0, &c2c.tool); | |
56 | if (session == NULL) { | |
57 | pr_debug("No memory for session\n"); | |
58 | goto out; | |
59 | } | |
60 | ||
61 | if (symbol__init(&session->header.env) < 0) | |
62 | goto out_session; | |
63 | ||
64 | /* No pipe support at the moment. */ | |
65 | if (perf_data_file__is_pipe(session->file)) { | |
66 | pr_debug("No pipe support at the moment.\n"); | |
67 | goto out_session; | |
68 | } | |
69 | ||
70 | out_session: | |
71 | perf_session__delete(session); | |
72 | out: | |
73 | return err; | |
74 | } | |
75 | ||
39bcd4a4 JO |
76 | static int parse_record_events(const struct option *opt __maybe_unused, |
77 | const char *str, int unset __maybe_unused) | |
78 | { | |
79 | bool *event_set = (bool *) opt->value; | |
80 | ||
81 | *event_set = true; | |
82 | return perf_mem_events__parse(str); | |
83 | } | |
84 | ||
85 | ||
86 | static const char * const __usage_record[] = { | |
87 | "perf c2c record [<options>] [<command>]", | |
88 | "perf c2c record [<options>] -- <command> [<options>]", | |
89 | NULL | |
90 | }; | |
91 | ||
92 | static const char * const *record_mem_usage = __usage_record; | |
93 | ||
94 | static int perf_c2c__record(int argc, const char **argv) | |
95 | { | |
96 | int rec_argc, i = 0, j; | |
97 | const char **rec_argv; | |
98 | int ret; | |
99 | bool all_user = false, all_kernel = false; | |
100 | bool event_set = false; | |
101 | struct option options[] = { | |
102 | OPT_CALLBACK('e', "event", &event_set, "event", | |
103 | "event selector. Use 'perf mem record -e list' to list available events", | |
104 | parse_record_events), | |
105 | OPT_INCR('v', "verbose", &verbose, | |
106 | "be more verbose (show counter open errors, etc)"), | |
107 | OPT_BOOLEAN('u', "all-user", &all_user, "collect only user level data"), | |
108 | OPT_BOOLEAN('k', "all-kernel", &all_kernel, "collect only kernel level data"), | |
109 | OPT_UINTEGER('l', "ldlat", &perf_mem_events__loads_ldlat, "setup mem-loads latency"), | |
110 | OPT_END() | |
111 | }; | |
112 | ||
113 | if (perf_mem_events__init()) { | |
114 | pr_err("failed: memory events not supported\n"); | |
115 | return -1; | |
116 | } | |
117 | ||
118 | argc = parse_options(argc, argv, options, record_mem_usage, | |
119 | PARSE_OPT_KEEP_UNKNOWN); | |
120 | ||
121 | rec_argc = argc + 10; /* max number of arguments */ | |
122 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); | |
123 | if (!rec_argv) | |
124 | return -1; | |
125 | ||
126 | rec_argv[i++] = "record"; | |
127 | ||
128 | if (!event_set) { | |
129 | perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true; | |
130 | perf_mem_events[PERF_MEM_EVENTS__STORE].record = true; | |
131 | } | |
132 | ||
133 | if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record) | |
134 | rec_argv[i++] = "-W"; | |
135 | ||
136 | rec_argv[i++] = "-d"; | |
137 | rec_argv[i++] = "--sample-cpu"; | |
138 | ||
139 | for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { | |
140 | if (!perf_mem_events[j].record) | |
141 | continue; | |
142 | ||
143 | if (!perf_mem_events[j].supported) { | |
144 | pr_err("failed: event '%s' not supported\n", | |
145 | perf_mem_events[j].name); | |
146 | return -1; | |
147 | } | |
148 | ||
149 | rec_argv[i++] = "-e"; | |
150 | rec_argv[i++] = perf_mem_events__name(j); | |
151 | }; | |
152 | ||
153 | if (all_user) | |
154 | rec_argv[i++] = "--all-user"; | |
155 | ||
156 | if (all_kernel) | |
157 | rec_argv[i++] = "--all-kernel"; | |
158 | ||
159 | for (j = 0; j < argc; j++, i++) | |
160 | rec_argv[i] = argv[j]; | |
161 | ||
162 | if (verbose > 0) { | |
163 | pr_debug("calling: "); | |
164 | ||
165 | j = 0; | |
166 | ||
167 | while (rec_argv[j]) { | |
168 | pr_debug("%s ", rec_argv[j]); | |
169 | j++; | |
170 | } | |
171 | pr_debug("\n"); | |
172 | } | |
173 | ||
174 | ret = cmd_record(i, rec_argv, NULL); | |
175 | free(rec_argv); | |
176 | return ret; | |
177 | } | |
178 | ||
7aef3bf3 JO |
179 | int cmd_c2c(int argc, const char **argv, const char *prefix __maybe_unused) |
180 | { | |
181 | const struct option c2c_options[] = { | |
182 | OPT_INCR('v', "verbose", &verbose, "be more verbose"), | |
183 | OPT_END() | |
184 | }; | |
185 | ||
186 | argc = parse_options(argc, argv, c2c_options, c2c_usage, | |
187 | PARSE_OPT_STOP_AT_NON_OPTION); | |
39bcd4a4 JO |
188 | |
189 | if (!argc) | |
190 | usage_with_options(c2c_usage, c2c_options); | |
191 | ||
192 | if (!strncmp(argv[0], "rec", 3)) { | |
193 | return perf_c2c__record(argc, argv); | |
903a6f15 JO |
194 | } else if (!strncmp(argv[0], "rep", 3)) { |
195 | return perf_c2c__report(argc, argv); | |
39bcd4a4 JO |
196 | } else { |
197 | usage_with_options(c2c_usage, c2c_options); | |
198 | } | |
199 | ||
7aef3bf3 JO |
200 | return 0; |
201 | } |