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