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 */
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"
22 #ifdef MALI_SUPPORT
23 #include "gator_events_mali_common.h"
24 #endif
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;
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 }
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 }
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 }
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 }
92 static void marshal_link(int cookie, int tgid, int pid)
93 {
94 unsigned long cpu = get_physical_cpu(), flags;
95 u64 time;
97 local_irq_save(flags);
98 time = gator_get_time();
99 if (buffer_check_space(cpu, NAME_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
100 gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_LINK);
101 gator_buffer_write_packed_int64(cpu, NAME_BUF, time);
102 gator_buffer_write_packed_int(cpu, NAME_BUF, cookie);
103 gator_buffer_write_packed_int(cpu, NAME_BUF, tgid);
104 gator_buffer_write_packed_int(cpu, NAME_BUF, pid);
105 }
106 // Check and commit; commit is set to occur once buffer is 3/4 full
107 buffer_check(cpu, NAME_BUF, time);
108 local_irq_restore(flags);
109 }
111 static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, int inKernel, u64 time)
112 {
113 int cpu = get_physical_cpu();
114 if (!buffer_check_space(cpu, BACKTRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32 + gator_backtrace_depth * 2 * MAXSIZE_PACK32)) {
115 // Check and commit; commit is set to occur once buffer is 3/4 full
116 buffer_check(cpu, BACKTRACE_BUF, time);
118 return false;
119 }
121 gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, time);
122 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, exec_cookie);
123 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, tgid);
124 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, pid);
125 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, inKernel);
127 return true;
128 }
130 static void marshal_backtrace(unsigned long address, int cookie)
131 {
132 int cpu = get_physical_cpu();
133 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, cookie);
134 gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, address);
135 }
137 static void marshal_backtrace_footer(u64 time)
138 {
139 int cpu = get_physical_cpu();
140 gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_END_BACKTRACE);
142 // Check and commit; commit is set to occur once buffer is 3/4 full
143 buffer_check(cpu, BACKTRACE_BUF, time);
144 }
146 static bool marshal_event_header(u64 time)
147 {
148 unsigned long flags, cpu = get_physical_cpu();
149 bool retval = false;
151 local_irq_save(flags);
152 if (buffer_check_space(cpu, BLOCK_COUNTER_BUF, MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
153 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, 0); // key of zero indicates a timestamp
154 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, time);
155 retval = true;
156 }
157 local_irq_restore(flags);
159 return retval;
160 }
162 static void marshal_event(int len, int *buffer)
163 {
164 unsigned long i, flags, cpu = get_physical_cpu();
166 if (len <= 0)
167 return;
169 // length must be even since all data is a (key, value) pair
170 if (len & 0x1) {
171 pr_err("gator: invalid counter data detected and discarded");
172 return;
173 }
175 // events must be written in key,value pairs
176 local_irq_save(flags);
177 for (i = 0; i < len; i += 2) {
178 if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK32)) {
179 break;
180 }
181 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i]);
182 gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i + 1]);
183 }
184 local_irq_restore(flags);
185 }
187 static void marshal_event64(int len, long long *buffer64)
188 {
189 unsigned long i, flags, cpu = get_physical_cpu();
191 if (len <= 0)
192 return;
194 // length must be even since all data is a (key, value) pair
195 if (len & 0x1) {
196 pr_err("gator: invalid counter data detected and discarded");
197 return;
198 }
200 // events must be written in key,value pairs
201 local_irq_save(flags);
202 for (i = 0; i < len; i += 2) {
203 if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK64)) {
204 break;
205 }
206 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i]);
207 gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i + 1]);
208 }
209 local_irq_restore(flags);
210 }
212 #if GATOR_CPU_FREQ_SUPPORT
213 static void marshal_event_single(int core, int key, int value)
214 {
215 unsigned long flags, cpu;
216 u64 time;
218 local_irq_save(flags);
219 cpu = get_physical_cpu();
220 time = gator_get_time();
221 if (buffer_check_space(cpu, COUNTER_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) {
222 gator_buffer_write_packed_int64(cpu, COUNTER_BUF, time);
223 gator_buffer_write_packed_int(cpu, COUNTER_BUF, core);
224 gator_buffer_write_packed_int(cpu, COUNTER_BUF, key);
225 gator_buffer_write_packed_int(cpu, COUNTER_BUF, value);
226 }
227 // Check and commit; commit is set to occur once buffer is 3/4 full
228 buffer_check(cpu, COUNTER_BUF, time);
229 local_irq_restore(flags);
230 }
231 #endif
233 static void marshal_sched_gpu_start(int unit, int core, int tgid, int pid)
234 {
235 unsigned long cpu = get_physical_cpu(), flags;
236 u64 time;
238 if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF])
239 return;
241 local_irq_save(flags);
242 time = gator_get_time();
243 if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
244 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_START);
245 gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, time);
246 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit);
247 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core);
248 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, tgid);
249 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, pid);
250 }
251 // Check and commit; commit is set to occur once buffer is 3/4 full
252 buffer_check(cpu, GPU_TRACE_BUF, time);
253 local_irq_restore(flags);
254 }
256 static void marshal_sched_gpu_stop(int unit, int core)
257 {
258 unsigned long cpu = get_physical_cpu(), flags;
259 u64 time;
261 if (!per_cpu(gator_buffer, cpu)[GPU_TRACE_BUF])
262 return;
264 local_irq_save(flags);
265 time = gator_get_time();
266 if (buffer_check_space(cpu, GPU_TRACE_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) {
267 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, MESSAGE_GPU_STOP);
268 gator_buffer_write_packed_int64(cpu, GPU_TRACE_BUF, time);
269 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, unit);
270 gator_buffer_write_packed_int(cpu, GPU_TRACE_BUF, core);
271 }
272 // Check and commit; commit is set to occur once buffer is 3/4 full
273 buffer_check(cpu, GPU_TRACE_BUF, time);
274 local_irq_restore(flags);
275 }
277 static void marshal_sched_trace_start(int tgid, int pid, int cookie)
278 {
279 unsigned long cpu = get_physical_cpu(), flags;
280 u64 time;
282 if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
283 return;
285 local_irq_save(flags);
286 time = gator_get_time();
287 if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
288 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_START);
289 gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, time);
290 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, tgid);
291 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
292 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, cookie);
293 }
294 // Check and commit; commit is set to occur once buffer is 3/4 full
295 buffer_check(cpu, SCHED_TRACE_BUF, time);
296 local_irq_restore(flags);
297 }
299 static void marshal_sched_trace_switch(int tgid, int pid, int cookie, int state)
300 {
301 unsigned long cpu = get_physical_cpu(), flags;
302 u64 time;
304 if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
305 return;
307 local_irq_save(flags);
308 time = gator_get_time();
309 if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
310 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_SWITCH);
311 gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, time);
312 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, tgid);
313 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
314 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, cookie);
315 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, state);
316 }
317 // Check and commit; commit is set to occur once buffer is 3/4 full
318 buffer_check(cpu, SCHED_TRACE_BUF, time);
319 local_irq_restore(flags);
320 }
322 static void marshal_sched_trace_exit(int tgid, int pid)
323 {
324 unsigned long cpu = get_physical_cpu(), flags;
325 u64 time;
327 if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
328 return;
330 local_irq_save(flags);
331 time = gator_get_time();
332 if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) {
333 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_EXIT);
334 gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, time);
335 gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
336 }
337 // Check and commit; commit is set to occur once buffer is 3/4 full
338 buffer_check(cpu, SCHED_TRACE_BUF, time);
339 local_irq_restore(flags);
340 }
342 #if GATOR_CPU_FREQ_SUPPORT
343 static void marshal_idle(int core, int state)
344 {
345 unsigned long flags, cpu;
346 u64 time;
348 local_irq_save(flags);
349 cpu = get_physical_cpu();
350 time = gator_get_time();
351 if (buffer_check_space(cpu, IDLE_BUF, MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) {
352 gator_buffer_write_packed_int(cpu, IDLE_BUF, state);
353 gator_buffer_write_packed_int64(cpu, IDLE_BUF, time);
354 gator_buffer_write_packed_int(cpu, IDLE_BUF, core);
355 }
356 // Check and commit; commit is set to occur once buffer is 3/4 full
357 buffer_check(cpu, IDLE_BUF, time);
358 local_irq_restore(flags);
359 }
360 #endif
362 static void marshal_frame(int cpu, int buftype)
363 {
364 int frame;
366 if (!per_cpu(gator_buffer, cpu)[buftype]) {
367 return;
368 }
370 switch (buftype) {
371 case SUMMARY_BUF:
372 frame = FRAME_SUMMARY;
373 break;
374 case BACKTRACE_BUF:
375 frame = FRAME_BACKTRACE;
376 break;
377 case NAME_BUF:
378 frame = FRAME_NAME;
379 break;
380 case COUNTER_BUF:
381 frame = FRAME_COUNTER;
382 break;
383 case BLOCK_COUNTER_BUF:
384 frame = FRAME_BLOCK_COUNTER;
385 break;
386 case ANNOTATE_BUF:
387 frame = FRAME_ANNOTATE;
388 break;
389 case SCHED_TRACE_BUF:
390 frame = FRAME_SCHED_TRACE;
391 break;
392 case GPU_TRACE_BUF:
393 frame = FRAME_GPU_TRACE;
394 break;
395 case IDLE_BUF:
396 frame = FRAME_IDLE;
397 break;
398 default:
399 frame = -1;
400 break;
401 }
403 // add response type
404 if (gator_response_type > 0) {
405 gator_buffer_write_packed_int(cpu, buftype, gator_response_type);
406 }
408 // leave space for 4-byte unpacked length
409 per_cpu(gator_buffer_write, cpu)[buftype] = (per_cpu(gator_buffer_write, cpu)[buftype] + sizeof(s32)) & gator_buffer_mask[buftype];
411 // add frame type and core number
412 gator_buffer_write_packed_int(cpu, buftype, frame);
413 gator_buffer_write_packed_int(cpu, buftype, cpu);
414 }
416 #if defined(__arm__) || defined(__aarch64__)
417 static void marshal_core_name(const int core, const int cpuid, const char *name)
418 {
419 int cpu = get_physical_cpu();
420 unsigned long flags;
421 local_irq_save(flags);
422 if (buffer_check_space(cpu, NAME_BUF, MAXSIZE_PACK32 + MAXSIZE_CORE_NAME)) {
423 gator_buffer_write_packed_int(cpu, NAME_BUF, HRTIMER_CORE_NAME);
424 gator_buffer_write_packed_int(cpu, NAME_BUF, core);
425 gator_buffer_write_packed_int(cpu, NAME_BUF, cpuid);
426 gator_buffer_write_string(cpu, NAME_BUF, name);
427 }
428 // Commit core names now so that they can show up in live
429 gator_commit_buffer(cpu, NAME_BUF, gator_get_time());
430 local_irq_restore(flags);
431 }
432 #endif