Merge tag 'v3.10.23' into linux-linaro-lsk
[firefly-linux-kernel-4.4.55.git] / drivers / gator / gator_marshaling.c
1 /**
2  * Copyright (C) ARM Limited 2012-2013. 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_string(cpu, SUMMARY_BUF, NEWLINE_CANARY);
33         gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, timestamp);
34         gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, uptime);
35         gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, monotonic_delta);
36         gator_buffer_write_string(cpu, SUMMARY_BUF, "uname");
37         gator_buffer_write_string(cpu, SUMMARY_BUF, uname);
38 #if GATOR_IKS_SUPPORT
39         gator_buffer_write_string(cpu, SUMMARY_BUF, "iks");
40         gator_buffer_write_string(cpu, SUMMARY_BUF, "");
41 #endif
42         // 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.
43 #ifdef MALI_SUPPORT
44         gator_buffer_write_string(cpu, SUMMARY_BUF, "mali_type");
45 #if (MALI_SUPPORT == MALI_4xx)
46         gator_buffer_write_string(cpu, SUMMARY_BUF, "4xx");
47 #elif (MALI_SUPPORT == MALI_T6xx)
48         gator_buffer_write_string(cpu, SUMMARY_BUF, "6xx");
49 #else
50         gator_buffer_write_string(cpu, SUMMARY_BUF, "unknown");
51 #endif
52 #endif
53         gator_buffer_write_string(cpu, SUMMARY_BUF, "");
54         // Commit the buffer now so it can be one of the first frames read by Streamline
55         gator_commit_buffer(cpu, SUMMARY_BUF, gator_get_time());
56         local_irq_restore(flags);
57 }
58
59 static bool marshal_cookie_header(const char *text)
60 {
61         int cpu = get_physical_cpu();
62         return buffer_check_space(cpu, NAME_BUF, strlen(text) + 3 * MAXSIZE_PACK32);
63 }
64
65 static void marshal_cookie(int cookie, const char *text)
66 {
67         int cpu = get_physical_cpu();
68         // buffer_check_space already called by marshal_cookie_header
69         gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_COOKIE);
70         gator_buffer_write_packed_int(cpu, NAME_BUF, cookie);
71         gator_buffer_write_string(cpu, NAME_BUF, text);
72         buffer_check(cpu, NAME_BUF, gator_get_time());
73 }
74
75 static void marshal_thread_name(int pid, char *name)
76 {
77         unsigned long flags, cpu;
78         u64 time;
79         local_irq_save(flags);
80         cpu = get_physical_cpu();
81         time = gator_get_time();
82         if (buffer_check_space(cpu, NAME_BUF, TASK_COMM_LEN + 3 * MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
83                 gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_THREAD_NAME);
84                 gator_buffer_write_packed_int64(cpu, NAME_BUF, time);
85                 gator_buffer_write_packed_int(cpu, NAME_BUF, pid);
86                 gator_buffer_write_string(cpu, NAME_BUF, name);
87         }
88         buffer_check(cpu, NAME_BUF, time);
89         local_irq_restore(flags);
90 }
91
92 static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inKernel, u64 time)
93 {
94         int cpu = get_physical_cpu();
95         if (!buffer_check_space(cpu, BACKTRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32 + gator_backtrace_depth * 2 * MAXSIZE_PACK32)) {
96                 // Check and commit; commit is set to occur once buffer is 3/4 full
97                 buffer_check(cpu, BACKTRACE_BUF, time);
98
99                 return false;
100         }
101
102         gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, time);
103         gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, exec_cookie);
104         gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, tgid);
105         gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, pid);
106         gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, inKernel);
107
108         return true;
109 }
110
111 static void marshal_backtrace(unsigned long address, int cookie)
112 {
113         int cpu = get_physical_cpu();
114         gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, cookie);
115         gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, address);
116 }
117
118 static void marshal_backtrace_footer(u64 time)
119 {
120         int cpu = get_physical_cpu();
121         gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_END_BACKTRACE);
122
123         // Check and commit; commit is set to occur once buffer is 3/4 full
124         buffer_check(cpu, BACKTRACE_BUF, time);
125 }
126
127 static bool marshal_event_header(u64 time)
128 {
129         unsigned long flags, cpu = get_physical_cpu();
130         bool retval = false;
131
132         local_irq_save(flags);
133         if (buffer_check_space(cpu, BLOCK_COUNTER_BUF, MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
134                 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, 0);       // key of zero indicates a timestamp
135                 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, time);
136                 retval = true;
137         }
138         local_irq_restore(flags);
139
140         return retval;
141 }
142
143 static void marshal_event(int len, int *buffer)
144 {
145         unsigned long i, flags, cpu = get_physical_cpu();
146
147         if (len <= 0)
148                 return;
149
150         // length must be even since all data is a (key, value) pair
151         if (len & 0x1) {
152                 pr_err("gator: invalid counter data detected and discarded");
153                 return;
154         }
155
156         // events must be written in key,value pairs
157         local_irq_save(flags);
158         for (i = 0; i < len; i += 2) {
159                 if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK32)) {
160                         break;
161                 }
162                 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i]);
163                 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i + 1]);
164         }
165         local_irq_restore(flags);
166 }
167
168 static void marshal_event64(int len, long long *buffer64)
169 {
170         unsigned long i, flags, cpu = get_physical_cpu();
171
172         if (len <= 0)
173                 return;
174
175         // length must be even since all data is a (key, value) pair
176         if (len & 0x1) {
177                 pr_err("gator: invalid counter data detected and discarded");
178                 return;
179         }
180
181         // events must be written in key,value pairs
182         local_irq_save(flags);
183         for (i = 0; i < len; i += 2) {
184                 if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK64)) {
185                         break;
186                 }
187                 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i]);
188                 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i + 1]);
189         }
190         local_irq_restore(flags);
191 }
192
193 #if GATOR_CPU_FREQ_SUPPORT
194 static void marshal_event_single(int core, int key, int value)
195 {
196         unsigned long flags, cpu;
197         u64 time;
198
199         local_irq_save(flags);
200         cpu = get_physical_cpu();
201         time = gator_get_time();
202         if (buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) {
203                 gator_buffer_write_packed_int64(cpu, COUNTER_BUF, time);
204                 gator_buffer_write_packed_int(cpu, COUNTER_BUF, core);
205                 gator_buffer_write_packed_int(cpu, COUNTER_BUF, key);
206                 gator_buffer_write_packed_int(cpu, COUNTER_BUF, value);
207         }
208         // Check and commit; commit is set to occur once buffer is 3/4 full
209         buffer_check(cpu, COUNTER_BUF, time);
210         local_irq_restore(flags);
211 }
212 #endif
213
214 static void marshal_sched_gpu_start(int unit, int core, int tgid, int pid)
215 {
216         unsigned long cpu = get_physical_cpu(), flags;
217         u64 time;
218
219         if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF])
220                 return;
221
222         local_irq_save(flags);
223         time = gator_get_time();
224         if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
225                 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_START);
226                 gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, time);
227                 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit);
228                 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core);
229                 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, tgid);
230                 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, pid);
231         }
232         // Check and commit; commit is set to occur once buffer is 3/4 full
233         buffer_check(cpu, GPU_TRACE_BUF, time);
234         local_irq_restore(flags);
235 }
236
237 static void marshal_sched_gpu_stop(int unit, int core)
238 {
239         unsigned long cpu = get_physical_cpu(), flags;
240         u64 time;
241
242         if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF])
243                 return;
244
245         local_irq_save(flags);
246         time = gator_get_time();
247         if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) {
248                 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_STOP);
249                 gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, time);
250                 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit);
251                 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core);
252         }
253         // Check and commit; commit is set to occur once buffer is 3/4 full
254         buffer_check(cpu, GPU_TRACE_BUF, time);
255         local_irq_restore(flags);
256 }
257
258 static void marshal_sched_trace_start(int tgid, int pid, int cookie)
259 {
260         unsigned long cpu = get_physical_cpu(), flags;
261         u64 time;
262
263         if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
264                 return;
265
266         local_irq_save(flags);
267         time = gator_get_time();
268         if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
269                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_START);
270                 gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, time);
271                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, tgid);
272                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
273                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, cookie);
274         }
275         // Check and commit; commit is set to occur once buffer is 3/4 full
276         buffer_check(cpu, SCHED_TRACE_BUF, time);
277         local_irq_restore(flags);
278 }
279
280 static void marshal_sched_trace_switch(int tgid, int pid, int cookie, int state)
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_SWITCH);
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                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, state);
297         }
298         // Check and commit; commit is set to occur once buffer is 3/4 full
299         buffer_check(cpu, SCHED_TRACE_BUF, time);
300         local_irq_restore(flags);
301 }
302
303 static void marshal_sched_trace_exit(int tgid, int pid)
304 {
305         unsigned long cpu = get_physical_cpu(), flags;
306         u64 time;
307
308         if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
309                 return;
310
311         local_irq_save(flags);
312         time = gator_get_time();
313         if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) {
314                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_EXIT);
315                 gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, time);
316                 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
317         }
318         // Check and commit; commit is set to occur once buffer is 3/4 full
319         buffer_check(cpu, SCHED_TRACE_BUF, time);
320         local_irq_restore(flags);
321 }
322
323 #if GATOR_CPU_FREQ_SUPPORT
324 static void marshal_idle(int core, int state)
325 {
326         unsigned long flags, cpu;
327         u64 time;
328
329         local_irq_save(flags);
330         cpu = get_physical_cpu();
331         time = gator_get_time();
332         if (buffer_check_space(cpu, IDLE_BUF, MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) {
333                 gator_buffer_write_packed_int(cpu, IDLE_BUF, state);
334                 gator_buffer_write_packed_int64(cpu, IDLE_BUF, time);
335                 gator_buffer_write_packed_int(cpu, IDLE_BUF, core);
336         }
337         // Check and commit; commit is set to occur once buffer is 3/4 full
338         buffer_check(cpu, IDLE_BUF, time);
339         local_irq_restore(flags);
340 }
341 #endif
342
343 static void marshal_frame(int cpu, int buftype)
344 {
345         int frame;
346
347         if (!per_cpu(gator_buffer, cpu)[buftype]) {
348                 return;
349         }
350
351         switch (buftype) {
352         case SUMMARY_BUF:
353                 frame = FRAME_SUMMARY;
354                 break;
355         case BACKTRACE_BUF:
356                 frame = FRAME_BACKTRACE;
357                 break;
358         case NAME_BUF:
359                 frame = FRAME_NAME;
360                 break;
361         case COUNTER_BUF:
362                 frame = FRAME_COUNTER;
363                 break;
364         case BLOCK_COUNTER_BUF:
365                 frame = FRAME_BLOCK_COUNTER;
366                 break;
367         case ANNOTATE_BUF:
368                 frame = FRAME_ANNOTATE;
369                 break;
370         case SCHED_TRACE_BUF:
371                 frame = FRAME_SCHED_TRACE;
372                 break;
373         case GPU_TRACE_BUF:
374                 frame = FRAME_GPU_TRACE;
375                 break;
376         case IDLE_BUF:
377                 frame = FRAME_IDLE;
378                 break;
379         default:
380                 frame = -1;
381                 break;
382         }
383
384         // add response type
385         if (gator_response_type > 0) {
386                 gator_buffer_write_packed_int(cpu, buftype, gator_response_type);
387         }
388
389         // leave space for 4-byte unpacked length
390         per_cpu(gator_buffer_write, cpu)[buftype] = (per_cpu(gator_buffer_write, cpu)[buftype] + sizeof(s32)) & gator_buffer_mask[buftype];
391
392         // add frame type and core number
393         gator_buffer_write_packed_int(cpu, buftype, frame);
394         gator_buffer_write_packed_int(cpu, buftype, cpu);
395 }
396
397 #if defined(__arm__) || defined(__aarch64__)
398 static void marshal_core_name(const int core, const int cpuid, const char *name)
399 {
400         int cpu = get_physical_cpu();
401         unsigned long flags;
402         local_irq_save(flags);
403         if (buffer_check_space(cpu, NAME_BUF, MAXSIZE_PACK32 + MAXSIZE_CORE_NAME)) {
404                 gator_buffer_write_packed_int(cpu, NAME_BUF, HRTIMER_CORE_NAME);
405                 gator_buffer_write_packed_int(cpu, NAME_BUF, core);
406                 gator_buffer_write_packed_int(cpu, NAME_BUF, cpuid);
407                 gator_buffer_write_string(cpu, NAME_BUF, name);
408         }
409         // Commit core names now so that they can show up in live
410         gator_commit_buffer(cpu, NAME_BUF, gator_get_time());
411         local_irq_restore(flags);
412 }
413 #endif