Merge tag 'v3.10.46' into linux-linaro-lsk
[firefly-linux-kernel-4.4.55.git] / drivers / gator / gator_marshaling.c
1 /**
2  * Copyright (C) ARM Limited 2012-2014. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  */
9
10 #define NEWLINE_CANARY \
11         /* Unix */ \
12         "1\n" \
13         /* Windows */ \
14         "2\r\n" \
15         /* Mac OS */ \
16         "3\r" \
17         /* RISC OS */ \
18         "4\n\r" \
19         /* Add another character so the length isn't 0x0a bytes */ \
20         "5"
21
22 #ifdef MALI_SUPPORT
23 #include "gator_events_mali_common.h"
24 #endif
25
26 static void marshal_summary(long long timestamp, long long uptime, long long monotonic_delta, const char * uname)
27 {
28         unsigned long flags;
29         int cpu = 0;
30
31         local_irq_save(flags);
32         gator_buffer_write_packed_int(cpu, SUMMARY_BUF, MESSAGE_SUMMARY);
33         gator_buffer_write_string(cpu, SUMMARY_BUF, NEWLINE_CANARY);
34         gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, timestamp);
35         gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, uptime);
36         gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, monotonic_delta);
37         gator_buffer_write_string(cpu, SUMMARY_BUF, "uname");
38         gator_buffer_write_string(cpu, SUMMARY_BUF, uname);
39 #if GATOR_IKS_SUPPORT
40         gator_buffer_write_string(cpu, SUMMARY_BUF, "iks");
41         gator_buffer_write_string(cpu, SUMMARY_BUF, "");
42 #endif
43         // Let Streamline know which GPU is used so that it can label the GPU Activity appropriately. This is a temporary fix, to be improved in a future release.
44 #ifdef MALI_SUPPORT
45         gator_buffer_write_string(cpu, SUMMARY_BUF, "mali_type");
46 #if (MALI_SUPPORT == MALI_4xx)
47         gator_buffer_write_string(cpu, SUMMARY_BUF, "4xx");
48 #elif (MALI_SUPPORT == MALI_T6xx)
49         gator_buffer_write_string(cpu, SUMMARY_BUF, "6xx");
50 #else
51         gator_buffer_write_string(cpu, SUMMARY_BUF, "unknown");
52 #endif
53 #endif
54         gator_buffer_write_string(cpu, SUMMARY_BUF, "");
55         // Commit the buffer now so it can be one of the first frames read by Streamline
56         local_irq_restore(flags);
57         gator_commit_buffer(cpu, SUMMARY_BUF, gator_get_time());
58 }
59
60 static bool marshal_cookie_header(const char *text)
61 {
62         int cpu = get_physical_cpu();
63         return buffer_check_space(cpu, NAME_BUF, strlen(text) + 3 * MAXSIZE_PACK32);
64 }
65
66 static void marshal_cookie(int cookie, const char *text)
67 {
68         int cpu = get_physical_cpu();
69         // buffer_check_space already called by marshal_cookie_header
70         gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_COOKIE);
71         gator_buffer_write_packed_int(cpu, NAME_BUF, cookie);
72         gator_buffer_write_string(cpu, NAME_BUF, text);
73         buffer_check(cpu, NAME_BUF, gator_get_time());
74 }
75
76 static void marshal_thread_name(int pid, char *name)
77 {
78         unsigned long flags, cpu;
79         u64 time;
80         local_irq_save(flags);
81         cpu = get_physical_cpu();
82         time = gator_get_time();
83         if (buffer_check_space(cpu, NAME_BUF, TASK_COMM_LEN + 3 * MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
84                 gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_THREAD_NAME);
85                 gator_buffer_write_packed_int64(cpu, NAME_BUF, time);
86                 gator_buffer_write_packed_int(cpu, NAME_BUF, pid);
87                 gator_buffer_write_string(cpu, NAME_BUF, name);
88         }
89         local_irq_restore(flags);
90         buffer_check(cpu, NAME_BUF, time);
91 }
92
93 static void marshal_link(int cookie, int tgid, int pid)
94 {
95         unsigned long cpu = get_physical_cpu(), flags;
96         u64 time;
97
98         local_irq_save(flags);
99         time = gator_get_time();
100         if (buffer_check_space(cpu, NAME_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
101                 gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_LINK);
102                 gator_buffer_write_packed_int64(cpu, NAME_BUF, time);
103                 gator_buffer_write_packed_int(cpu, NAME_BUF, cookie);
104                 gator_buffer_write_packed_int(cpu, NAME_BUF, tgid);
105                 gator_buffer_write_packed_int(cpu, NAME_BUF, pid);
106         }
107         local_irq_restore(flags);
108         // Check and commit; commit is set to occur once buffer is 3/4 full
109         buffer_check(cpu, NAME_BUF, time);
110 }
111
112 static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, u64 time)
113 {
114         int cpu = get_physical_cpu();
115         if (!buffer_check_space(cpu, BACKTRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32 + gator_backtrace_depth * 2 * MAXSIZE_PACK32)) {
116                 // Check and commit; commit is set to occur once buffer is 3/4 full
117                 buffer_check(cpu, BACKTRACE_BUF, time);
118
119                 return false;
120         }
121
122         gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, time);
123         gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, exec_cookie);
124         gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, tgid);
125         gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, pid);
126
127         return true;
128 }
129
130 static void marshal_backtrace(unsigned long address, int cookie, int in_kernel)
131 {
132         int cpu = get_physical_cpu();
133         if (cookie == 0 && !in_kernel) {
134                 cookie = UNRESOLVED_COOKIE;
135         }
136         gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, cookie);
137         gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, address);
138 }
139
140 static void marshal_backtrace_footer(u64 time)
141 {
142         int cpu = get_physical_cpu();
143         gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_END_BACKTRACE);
144
145         // Check and commit; commit is set to occur once buffer is 3/4 full
146         buffer_check(cpu, BACKTRACE_BUF, time);
147 }
148
149 static bool marshal_event_header(u64 time)
150 {
151         unsigned long flags, cpu = get_physical_cpu();
152         bool retval = false;
153
154         local_irq_save(flags);
155         if (buffer_check_space(cpu, BLOCK_COUNTER_BUF, MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
156                 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, 0);       // key of zero indicates a timestamp
157                 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, time);
158                 retval = true;
159         }
160         local_irq_restore(flags);
161
162         return retval;
163 }
164
165 static void marshal_event(int len, int *buffer)
166 {
167         unsigned long i, flags, cpu = get_physical_cpu();
168
169         if (len <= 0)
170                 return;
171
172         // length must be even since all data is a (key, value) pair
173         if (len & 0x1) {
174                 pr_err("gator: invalid counter data detected and discarded");
175                 return;
176         }
177
178         // events must be written in key,value pairs
179         local_irq_save(flags);
180         for (i = 0; i < len; i += 2) {
181                 if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK32)) {
182                         break;
183                 }
184                 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i]);
185                 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i + 1]);
186         }
187         local_irq_restore(flags);
188 }
189
190 static void marshal_event64(int len, long long *buffer64)
191 {
192         unsigned long i, flags, cpu = get_physical_cpu();
193
194         if (len <= 0)
195                 return;
196
197         // length must be even since all data is a (key, value) pair
198         if (len & 0x1) {
199                 pr_err("gator: invalid counter data detected and discarded");
200                 return;
201         }
202
203         // events must be written in key,value pairs
204         local_irq_save(flags);
205         for (i = 0; i < len; i += 2) {
206                 if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK64)) {
207                         break;
208                 }
209                 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i]);
210                 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i + 1]);
211         }
212         local_irq_restore(flags);
213 }
214
215 #if GATOR_CPU_FREQ_SUPPORT
216 static void marshal_event_single(int core, int key, int value)
217 {
218         unsigned long flags, cpu;
219         u64 time;
220
221         local_irq_save(flags);
222         cpu = get_physical_cpu();
223         time = gator_get_time();
224         if (buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) {
225                 gator_buffer_write_packed_int64(cpu, COUNTER_BUF, time);
226                 gator_buffer_write_packed_int(cpu, COUNTER_BUF, core);
227                 gator_buffer_write_packed_int(cpu, COUNTER_BUF, key);
228                 gator_buffer_write_packed_int(cpu, COUNTER_BUF, value);
229         }
230         local_irq_restore(flags);
231         // Check and commit; commit is set to occur once buffer is 3/4 full
232         buffer_check(cpu, COUNTER_BUF, time);
233 }
234 #endif
235
236 static void marshal_sched_gpu_start(int unit, int core, int tgid, int pid)
237 {
238         unsigned long cpu = get_physical_cpu(), flags;
239         u64 time;
240
241         if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF])
242                 return;
243
244         local_irq_save(flags);
245         time = gator_get_time();
246         if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
247                 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_START);
248                 gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, time);
249                 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit);
250                 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core);
251                 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, tgid);
252                 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, pid);
253         }
254         local_irq_restore(flags);
255         // Check and commit; commit is set to occur once buffer is 3/4 full
256         buffer_check(cpu, GPU_TRACE_BUF, time);
257 }
258
259 static void marshal_sched_gpu_stop(int unit, int core)
260 {
261         unsigned long cpu = get_physical_cpu(), flags;
262         u64 time;
263
264         if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF])
265                 return;
266
267         local_irq_save(flags);
268         time = gator_get_time();
269         if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) {
270                 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_STOP);
271                 gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, time);
272                 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit);
273                 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core);
274         }
275         local_irq_restore(flags);
276         // Check and commit; commit is set to occur once buffer is 3/4 full
277         buffer_check(cpu, GPU_TRACE_BUF, time);
278 }
279
280 static void marshal_sched_trace_start(int tgid, int pid, int cookie)
281 {
282         unsigned long cpu = get_physical_cpu(), flags;
283         u64 time;
284
285         if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
286                 return;
287
288         local_irq_save(flags);
289         time = gator_get_time();
290         if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
291                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_START);
292                 gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, time);
293                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, tgid);
294                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
295                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, cookie);
296         }
297         local_irq_restore(flags);
298         // Check and commit; commit is set to occur once buffer is 3/4 full
299         buffer_check(cpu, SCHED_TRACE_BUF, time);
300 }
301
302 static void marshal_sched_trace_switch(int tgid, int pid, int cookie, int state)
303 {
304         unsigned long cpu = get_physical_cpu(), flags;
305         u64 time;
306
307         if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
308                 return;
309
310         local_irq_save(flags);
311         time = gator_get_time();
312         if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
313                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_SWITCH);
314                 gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, time);
315                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, tgid);
316                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
317                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, cookie);
318                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, state);
319         }
320         local_irq_restore(flags);
321         // Check and commit; commit is set to occur once buffer is 3/4 full
322         buffer_check(cpu, SCHED_TRACE_BUF, time);
323 }
324
325 static void marshal_sched_trace_exit(int tgid, int pid)
326 {
327         unsigned long cpu = get_physical_cpu(), flags;
328         u64 time;
329
330         if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
331                 return;
332
333         local_irq_save(flags);
334         time = gator_get_time();
335         if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) {
336                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_EXIT);
337                 gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, time);
338                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
339         }
340         local_irq_restore(flags);
341         // Check and commit; commit is set to occur once buffer is 3/4 full
342         buffer_check(cpu, SCHED_TRACE_BUF, time);
343 }
344
345 #if GATOR_CPU_FREQ_SUPPORT
346 static void marshal_idle(int core, int state)
347 {
348         unsigned long flags, cpu;
349         u64 time;
350
351         local_irq_save(flags);
352         cpu = get_physical_cpu();
353         time = gator_get_time();
354         if (buffer_check_space(cpu, IDLE_BUF, MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) {
355                 gator_buffer_write_packed_int(cpu, IDLE_BUF, state);
356                 gator_buffer_write_packed_int64(cpu, IDLE_BUF, time);
357                 gator_buffer_write_packed_int(cpu, IDLE_BUF, core);
358         }
359         local_irq_restore(flags);
360         // Check and commit; commit is set to occur once buffer is 3/4 full
361         buffer_check(cpu, IDLE_BUF, time);
362 }
363 #endif
364
365 #if defined(__arm__) || defined(__aarch64__)
366 static void marshal_core_name(const int core, const int cpuid, const char *name)
367 {
368         int cpu = get_physical_cpu();
369         unsigned long flags;
370         local_irq_save(flags);
371         if (buffer_check_space(cpu, SUMMARY_BUF, MAXSIZE_PACK32 + MAXSIZE_CORE_NAME)) {
372                 gator_buffer_write_packed_int(cpu, SUMMARY_BUF, MESSAGE_CORE_NAME);
373                 gator_buffer_write_packed_int(cpu, SUMMARY_BUF, core);
374                 gator_buffer_write_packed_int(cpu, SUMMARY_BUF, cpuid);
375                 gator_buffer_write_string(cpu, SUMMARY_BUF, name);
376         }
377         // Commit core names now so that they can show up in live
378         local_irq_restore(flags);
379         gator_commit_buffer(cpu, SUMMARY_BUF, gator_get_time());
380 }
381 #endif