blob: 3b3ac7c143e1b1de9679e3f8d1fad61d8dcf3dc4 [file] [log] [blame]
Jiri Olsaedbe9812015-02-20 23:17:00 +01001/*
2 * CTF writing support via babeltrace.
3 *
4 * Copyright (C) 2014, Jiri Olsa <jolsa@redhat.com>
5 * Copyright (C) 2014, Sebastian Andrzej Siewior <bigeasy@linutronix.de>
6 *
7 * Released under the GPL v2. (and only v2, not any later version)
8 */
9
10#include <linux/compiler.h>
11#include <babeltrace/ctf-writer/writer.h>
12#include <babeltrace/ctf-writer/clock.h>
13#include <babeltrace/ctf-writer/stream.h>
14#include <babeltrace/ctf-writer/event.h>
15#include <babeltrace/ctf-writer/event-types.h>
16#include <babeltrace/ctf-writer/event-fields.h>
Wang Nane0a7cce2015-04-18 17:50:19 +020017#include <babeltrace/ctf-ir/utils.h>
Jiri Olsaedbe9812015-02-20 23:17:00 +010018#include <babeltrace/ctf/events.h>
19#include <traceevent/event-parse.h>
20#include "asm/bug.h"
21#include "data-convert-bt.h"
22#include "session.h"
23#include "util.h"
24#include "debug.h"
25#include "tool.h"
26#include "evlist.h"
27#include "evsel.h"
28#include "machine.h"
Jiri Olsaf6c12a02016-06-24 14:40:24 +020029#include "config.h"
Jiri Olsaedbe9812015-02-20 23:17:00 +010030
31#define pr_N(n, fmt, ...) \
32 eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
33
34#define pr(fmt, ...) pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
35#define pr2(fmt, ...) pr_N(2, pr_fmt(fmt), ##__VA_ARGS__)
36
37#define pr_time2(t, fmt, ...) pr_time_N(2, debug_data_convert, t, pr_fmt(fmt), ##__VA_ARGS__)
38
39struct evsel_priv {
40 struct bt_ctf_event_class *event_class;
41};
42
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +020043#define MAX_CPUS 4096
44
45struct ctf_stream {
46 struct bt_ctf_stream *stream;
47 int cpu;
Jiri Olsa89e5fa82015-04-18 17:50:16 +020048 u32 count;
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +020049};
50
Jiri Olsaedbe9812015-02-20 23:17:00 +010051struct ctf_writer {
52 /* writer primitives */
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +020053 struct bt_ctf_writer *writer;
54 struct ctf_stream **stream;
55 int stream_cnt;
56 struct bt_ctf_stream_class *stream_class;
57 struct bt_ctf_clock *clock;
Jiri Olsaedbe9812015-02-20 23:17:00 +010058
59 /* data types */
60 union {
61 struct {
62 struct bt_ctf_field_type *s64;
63 struct bt_ctf_field_type *u64;
64 struct bt_ctf_field_type *s32;
65 struct bt_ctf_field_type *u32;
66 struct bt_ctf_field_type *string;
Wang Nan26812d42015-12-08 02:25:39 +000067 struct bt_ctf_field_type *u32_hex;
Jiri Olsaedbe9812015-02-20 23:17:00 +010068 struct bt_ctf_field_type *u64_hex;
69 };
70 struct bt_ctf_field_type *array[6];
71 } data;
72};
73
74struct convert {
75 struct perf_tool tool;
76 struct ctf_writer writer;
77
78 u64 events_size;
79 u64 events_count;
Wang Nan8ee4c462016-06-24 11:22:09 +000080 u64 non_sample_count;
Jiri Olsa8fa46752015-04-18 17:50:17 +020081
82 /* Ordered events configured queue size. */
83 u64 queue_size;
Jiri Olsaedbe9812015-02-20 23:17:00 +010084};
85
86static int value_set(struct bt_ctf_field_type *type,
87 struct bt_ctf_event *event,
88 const char *name, u64 val)
89{
90 struct bt_ctf_field *field;
91 bool sign = bt_ctf_field_type_integer_get_signed(type);
92 int ret;
93
94 field = bt_ctf_field_create(type);
95 if (!field) {
96 pr_err("failed to create a field %s\n", name);
97 return -1;
98 }
99
100 if (sign) {
101 ret = bt_ctf_field_signed_integer_set_value(field, val);
102 if (ret) {
103 pr_err("failed to set field value %s\n", name);
104 goto err;
105 }
106 } else {
107 ret = bt_ctf_field_unsigned_integer_set_value(field, val);
108 if (ret) {
109 pr_err("failed to set field value %s\n", name);
110 goto err;
111 }
112 }
113
114 ret = bt_ctf_event_set_payload(event, name, field);
115 if (ret) {
116 pr_err("failed to set payload %s\n", name);
117 goto err;
118 }
119
120 pr2(" SET [%s = %" PRIu64 "]\n", name, val);
121
122err:
123 bt_ctf_field_put(field);
124 return ret;
125}
126
127#define __FUNC_VALUE_SET(_name, _val_type) \
128static __maybe_unused int value_set_##_name(struct ctf_writer *cw, \
129 struct bt_ctf_event *event, \
130 const char *name, \
131 _val_type val) \
132{ \
133 struct bt_ctf_field_type *type = cw->data._name; \
134 return value_set(type, event, name, (u64) val); \
135}
136
137#define FUNC_VALUE_SET(_name) __FUNC_VALUE_SET(_name, _name)
138
139FUNC_VALUE_SET(s32)
140FUNC_VALUE_SET(u32)
141FUNC_VALUE_SET(s64)
142FUNC_VALUE_SET(u64)
143__FUNC_VALUE_SET(u64_hex, u64)
144
Wang Nan069ee5c2016-06-24 11:22:06 +0000145static int string_set_value(struct bt_ctf_field *field, const char *string);
146static __maybe_unused int
147value_set_string(struct ctf_writer *cw, struct bt_ctf_event *event,
148 const char *name, const char *string)
149{
150 struct bt_ctf_field_type *type = cw->data.string;
151 struct bt_ctf_field *field;
152 int ret = 0;
153
154 field = bt_ctf_field_create(type);
155 if (!field) {
156 pr_err("failed to create a field %s\n", name);
157 return -1;
158 }
159
160 ret = string_set_value(field, string);
161 if (ret) {
162 pr_err("failed to set value %s\n", name);
163 goto err_put_field;
164 }
165
166 ret = bt_ctf_event_set_payload(event, name, field);
167 if (ret)
168 pr_err("failed to set payload %s\n", name);
169
170err_put_field:
171 bt_ctf_field_put(field);
172 return ret;
173}
174
Sebastian Andrzej Siewior69364722015-02-20 23:17:02 +0100175static struct bt_ctf_field_type*
176get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
177{
178 unsigned long flags = field->flags;
179
180 if (flags & FIELD_IS_STRING)
181 return cw->data.string;
182
183 if (!(flags & FIELD_IS_SIGNED)) {
184 /* unsigned long are mostly pointers */
185 if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER)
186 return cw->data.u64_hex;
187 }
188
189 if (flags & FIELD_IS_SIGNED) {
190 if (field->size == 8)
191 return cw->data.s64;
192 else
193 return cw->data.s32;
194 }
195
196 if (field->size == 8)
197 return cw->data.u64;
198 else
199 return cw->data.u32;
200}
201
Wang Nand4ae4212015-04-18 17:50:20 +0200202static unsigned long long adjust_signedness(unsigned long long value_int, int size)
203{
204 unsigned long long value_mask;
205
206 /*
207 * value_mask = (1 << (size * 8 - 1)) - 1.
208 * Directly set value_mask for code readers.
209 */
210 switch (size) {
211 case 1:
212 value_mask = 0x7fULL;
213 break;
214 case 2:
215 value_mask = 0x7fffULL;
216 break;
217 case 4:
218 value_mask = 0x7fffffffULL;
219 break;
220 case 8:
221 /*
222 * For 64 bit value, return it self. There is no need
223 * to fill high bit.
224 */
225 /* Fall through */
226 default:
227 /* BUG! */
228 return value_int;
229 }
230
231 /* If it is a positive value, don't adjust. */
232 if ((value_int & (~0ULL - value_mask)) == 0)
233 return value_int;
234
235 /* Fill upper part of value_int with 1 to make it a negative long long. */
236 return (value_int & value_mask) | ~value_mask;
237}
238
Wang Nan5ea58882016-05-27 11:35:51 +0000239static int string_set_value(struct bt_ctf_field *field, const char *string)
240{
241 char *buffer = NULL;
242 size_t len = strlen(string), i, p;
243 int err;
244
245 for (i = p = 0; i < len; i++, p++) {
246 if (isprint(string[i])) {
247 if (!buffer)
248 continue;
249 buffer[p] = string[i];
250 } else {
251 char numstr[5];
252
253 snprintf(numstr, sizeof(numstr), "\\x%02x",
254 (unsigned int)(string[i]) & 0xff);
255
256 if (!buffer) {
257 buffer = zalloc(i + (len - i) * 4 + 2);
258 if (!buffer) {
259 pr_err("failed to set unprintable string '%s'\n", string);
260 return bt_ctf_field_string_set_value(field, "UNPRINTABLE-STRING");
261 }
262 if (i > 0)
263 strncpy(buffer, string, i);
264 }
265 strncat(buffer + p, numstr, 4);
266 p += 3;
267 }
268 }
269
270 if (!buffer)
271 return bt_ctf_field_string_set_value(field, string);
272 err = bt_ctf_field_string_set_value(field, buffer);
273 free(buffer);
274 return err;
275}
276
Sebastian Andrzej Siewior69364722015-02-20 23:17:02 +0100277static int add_tracepoint_field_value(struct ctf_writer *cw,
278 struct bt_ctf_event_class *event_class,
279 struct bt_ctf_event *event,
280 struct perf_sample *sample,
281 struct format_field *fmtf)
282{
283 struct bt_ctf_field_type *type;
284 struct bt_ctf_field *array_field;
285 struct bt_ctf_field *field;
286 const char *name = fmtf->name;
287 void *data = sample->raw_data;
Sebastian Andrzej Siewior69364722015-02-20 23:17:02 +0100288 unsigned long flags = fmtf->flags;
289 unsigned int n_items;
290 unsigned int i;
291 unsigned int offset;
292 unsigned int len;
293 int ret;
294
Wang Nane0a7cce2015-04-18 17:50:19 +0200295 name = fmtf->alias;
Sebastian Andrzej Siewior69364722015-02-20 23:17:02 +0100296 offset = fmtf->offset;
297 len = fmtf->size;
298 if (flags & FIELD_IS_STRING)
299 flags &= ~FIELD_IS_ARRAY;
300
301 if (flags & FIELD_IS_DYNAMIC) {
302 unsigned long long tmp_val;
303
304 tmp_val = pevent_read_number(fmtf->event->pevent,
305 data + offset, len);
306 offset = tmp_val;
307 len = offset >> 16;
308 offset &= 0xffff;
309 }
310
311 if (flags & FIELD_IS_ARRAY) {
312
313 type = bt_ctf_event_class_get_field_by_name(
314 event_class, name);
315 array_field = bt_ctf_field_create(type);
316 bt_ctf_field_type_put(type);
317 if (!array_field) {
318 pr_err("Failed to create array type %s\n", name);
319 return -1;
320 }
321
322 len = fmtf->size / fmtf->arraylen;
323 n_items = fmtf->arraylen;
324 } else {
325 n_items = 1;
326 array_field = NULL;
327 }
328
329 type = get_tracepoint_field_type(cw, fmtf);
330
331 for (i = 0; i < n_items; i++) {
Sebastian Andrzej Siewior69364722015-02-20 23:17:02 +0100332 if (flags & FIELD_IS_ARRAY)
333 field = bt_ctf_field_array_get_field(array_field, i);
334 else
335 field = bt_ctf_field_create(type);
336
337 if (!field) {
338 pr_err("failed to create a field %s\n", name);
339 return -1;
340 }
341
342 if (flags & FIELD_IS_STRING)
Wang Nan5ea58882016-05-27 11:35:51 +0000343 ret = string_set_value(field, data + offset + i * len);
Wang Nand4ae4212015-04-18 17:50:20 +0200344 else {
345 unsigned long long value_int;
346
347 value_int = pevent_read_number(
348 fmtf->event->pevent,
349 data + offset + i * len, len);
350
351 if (!(flags & FIELD_IS_SIGNED))
352 ret = bt_ctf_field_unsigned_integer_set_value(
353 field, value_int);
354 else
355 ret = bt_ctf_field_signed_integer_set_value(
356 field, adjust_signedness(value_int, len));
357 }
358
Sebastian Andrzej Siewior69364722015-02-20 23:17:02 +0100359 if (ret) {
360 pr_err("failed to set file value %s\n", name);
361 goto err_put_field;
362 }
363 if (!(flags & FIELD_IS_ARRAY)) {
364 ret = bt_ctf_event_set_payload(event, name, field);
365 if (ret) {
366 pr_err("failed to set payload %s\n", name);
367 goto err_put_field;
368 }
369 }
370 bt_ctf_field_put(field);
371 }
372 if (flags & FIELD_IS_ARRAY) {
373 ret = bt_ctf_event_set_payload(event, name, array_field);
374 if (ret) {
375 pr_err("Failed add payload array %s\n", name);
376 return -1;
377 }
378 bt_ctf_field_put(array_field);
379 }
380 return 0;
381
382err_put_field:
383 bt_ctf_field_put(field);
384 return -1;
385}
386
387static int add_tracepoint_fields_values(struct ctf_writer *cw,
388 struct bt_ctf_event_class *event_class,
389 struct bt_ctf_event *event,
390 struct format_field *fields,
391 struct perf_sample *sample)
392{
393 struct format_field *field;
394 int ret;
395
396 for (field = fields; field; field = field->next) {
397 ret = add_tracepoint_field_value(cw, event_class, event, sample,
398 field);
399 if (ret)
400 return -1;
401 }
402 return 0;
403}
404
405static int add_tracepoint_values(struct ctf_writer *cw,
406 struct bt_ctf_event_class *event_class,
407 struct bt_ctf_event *event,
408 struct perf_evsel *evsel,
409 struct perf_sample *sample)
410{
411 struct format_field *common_fields = evsel->tp_format->format.common_fields;
412 struct format_field *fields = evsel->tp_format->format.fields;
413 int ret;
414
415 ret = add_tracepoint_fields_values(cw, event_class, event,
416 common_fields, sample);
417 if (!ret)
418 ret = add_tracepoint_fields_values(cw, event_class, event,
419 fields, sample);
420
421 return ret;
422}
423
Wang Nan6122d572016-02-26 09:31:56 +0000424static int
425add_bpf_output_values(struct bt_ctf_event_class *event_class,
426 struct bt_ctf_event *event,
427 struct perf_sample *sample)
428{
429 struct bt_ctf_field_type *len_type, *seq_type;
430 struct bt_ctf_field *len_field, *seq_field;
431 unsigned int raw_size = sample->raw_size;
432 unsigned int nr_elements = raw_size / sizeof(u32);
433 unsigned int i;
434 int ret;
435
436 if (nr_elements * sizeof(u32) != raw_size)
437 pr_warning("Incorrect raw_size (%u) in bpf output event, skip %lu bytes\n",
438 raw_size, nr_elements * sizeof(u32) - raw_size);
439
440 len_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_len");
441 len_field = bt_ctf_field_create(len_type);
442 if (!len_field) {
443 pr_err("failed to create 'raw_len' for bpf output event\n");
444 ret = -1;
445 goto put_len_type;
446 }
447
448 ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements);
449 if (ret) {
450 pr_err("failed to set field value for raw_len\n");
451 goto put_len_field;
452 }
453 ret = bt_ctf_event_set_payload(event, "raw_len", len_field);
454 if (ret) {
455 pr_err("failed to set payload to raw_len\n");
456 goto put_len_field;
457 }
458
459 seq_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_data");
460 seq_field = bt_ctf_field_create(seq_type);
461 if (!seq_field) {
462 pr_err("failed to create 'raw_data' for bpf output event\n");
463 ret = -1;
464 goto put_seq_type;
465 }
466
467 ret = bt_ctf_field_sequence_set_length(seq_field, len_field);
468 if (ret) {
469 pr_err("failed to set length of 'raw_data'\n");
470 goto put_seq_field;
471 }
472
473 for (i = 0; i < nr_elements; i++) {
474 struct bt_ctf_field *elem_field =
475 bt_ctf_field_sequence_get_field(seq_field, i);
476
477 ret = bt_ctf_field_unsigned_integer_set_value(elem_field,
478 ((u32 *)(sample->raw_data))[i]);
479
480 bt_ctf_field_put(elem_field);
481 if (ret) {
482 pr_err("failed to set raw_data[%d]\n", i);
483 goto put_seq_field;
484 }
485 }
486
487 ret = bt_ctf_event_set_payload(event, "raw_data", seq_field);
488 if (ret)
489 pr_err("failed to set payload for raw_data\n");
490
491put_seq_field:
492 bt_ctf_field_put(seq_field);
493put_seq_type:
494 bt_ctf_field_type_put(seq_type);
495put_len_field:
496 bt_ctf_field_put(len_field);
497put_len_type:
498 bt_ctf_field_type_put(len_type);
499 return ret;
500}
501
Jiri Olsaedbe9812015-02-20 23:17:00 +0100502static int add_generic_values(struct ctf_writer *cw,
503 struct bt_ctf_event *event,
504 struct perf_evsel *evsel,
505 struct perf_sample *sample)
506{
507 u64 type = evsel->attr.sample_type;
508 int ret;
509
510 /*
511 * missing:
512 * PERF_SAMPLE_TIME - not needed as we have it in
513 * ctf event header
514 * PERF_SAMPLE_READ - TODO
515 * PERF_SAMPLE_CALLCHAIN - TODO
516 * PERF_SAMPLE_RAW - tracepoint fields are handled separately
517 * PERF_SAMPLE_BRANCH_STACK - TODO
518 * PERF_SAMPLE_REGS_USER - TODO
519 * PERF_SAMPLE_STACK_USER - TODO
520 */
521
522 if (type & PERF_SAMPLE_IP) {
Sebastian Andrzej Siewior54cf7762015-02-20 23:17:01 +0100523 ret = value_set_u64_hex(cw, event, "perf_ip", sample->ip);
Jiri Olsaedbe9812015-02-20 23:17:00 +0100524 if (ret)
525 return -1;
526 }
527
528 if (type & PERF_SAMPLE_TID) {
Sebastian Andrzej Siewior54cf7762015-02-20 23:17:01 +0100529 ret = value_set_s32(cw, event, "perf_tid", sample->tid);
Jiri Olsaedbe9812015-02-20 23:17:00 +0100530 if (ret)
531 return -1;
532
Sebastian Andrzej Siewior54cf7762015-02-20 23:17:01 +0100533 ret = value_set_s32(cw, event, "perf_pid", sample->pid);
Jiri Olsaedbe9812015-02-20 23:17:00 +0100534 if (ret)
535 return -1;
536 }
537
538 if ((type & PERF_SAMPLE_ID) ||
539 (type & PERF_SAMPLE_IDENTIFIER)) {
Sebastian Andrzej Siewior54cf7762015-02-20 23:17:01 +0100540 ret = value_set_u64(cw, event, "perf_id", sample->id);
Jiri Olsaedbe9812015-02-20 23:17:00 +0100541 if (ret)
542 return -1;
543 }
544
545 if (type & PERF_SAMPLE_STREAM_ID) {
Sebastian Andrzej Siewior54cf7762015-02-20 23:17:01 +0100546 ret = value_set_u64(cw, event, "perf_stream_id", sample->stream_id);
Jiri Olsaedbe9812015-02-20 23:17:00 +0100547 if (ret)
548 return -1;
549 }
550
Jiri Olsaedbe9812015-02-20 23:17:00 +0100551 if (type & PERF_SAMPLE_PERIOD) {
Sebastian Andrzej Siewior54cf7762015-02-20 23:17:01 +0100552 ret = value_set_u64(cw, event, "perf_period", sample->period);
Jiri Olsaedbe9812015-02-20 23:17:00 +0100553 if (ret)
554 return -1;
555 }
556
557 if (type & PERF_SAMPLE_WEIGHT) {
Sebastian Andrzej Siewior54cf7762015-02-20 23:17:01 +0100558 ret = value_set_u64(cw, event, "perf_weight", sample->weight);
Jiri Olsaedbe9812015-02-20 23:17:00 +0100559 if (ret)
560 return -1;
561 }
562
563 if (type & PERF_SAMPLE_DATA_SRC) {
Sebastian Andrzej Siewior54cf7762015-02-20 23:17:01 +0100564 ret = value_set_u64(cw, event, "perf_data_src",
565 sample->data_src);
Jiri Olsaedbe9812015-02-20 23:17:00 +0100566 if (ret)
567 return -1;
568 }
569
570 if (type & PERF_SAMPLE_TRANSACTION) {
Sebastian Andrzej Siewior54cf7762015-02-20 23:17:01 +0100571 ret = value_set_u64(cw, event, "perf_transaction",
572 sample->transaction);
Jiri Olsaedbe9812015-02-20 23:17:00 +0100573 if (ret)
574 return -1;
575 }
576
577 return 0;
578}
579
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +0200580static int ctf_stream__flush(struct ctf_stream *cs)
581{
582 int err = 0;
583
584 if (cs) {
585 err = bt_ctf_stream_flush(cs->stream);
586 if (err)
587 pr_err("CTF stream %d flush failed\n", cs->cpu);
588
Jiri Olsa89e5fa82015-04-18 17:50:16 +0200589 pr("Flush stream for cpu %d (%u samples)\n",
590 cs->cpu, cs->count);
591
592 cs->count = 0;
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +0200593 }
594
595 return err;
596}
597
598static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu)
599{
600 struct ctf_stream *cs;
601 struct bt_ctf_field *pkt_ctx = NULL;
602 struct bt_ctf_field *cpu_field = NULL;
603 struct bt_ctf_stream *stream = NULL;
604 int ret;
605
606 cs = zalloc(sizeof(*cs));
607 if (!cs) {
608 pr_err("Failed to allocate ctf stream\n");
609 return NULL;
610 }
611
612 stream = bt_ctf_writer_create_stream(cw->writer, cw->stream_class);
613 if (!stream) {
614 pr_err("Failed to create CTF stream\n");
615 goto out;
616 }
617
618 pkt_ctx = bt_ctf_stream_get_packet_context(stream);
619 if (!pkt_ctx) {
620 pr_err("Failed to obtain packet context\n");
621 goto out;
622 }
623
624 cpu_field = bt_ctf_field_structure_get_field(pkt_ctx, "cpu_id");
625 bt_ctf_field_put(pkt_ctx);
626 if (!cpu_field) {
627 pr_err("Failed to obtain cpu field\n");
628 goto out;
629 }
630
631 ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu);
632 if (ret) {
633 pr_err("Failed to update CPU number\n");
634 goto out;
635 }
636
637 bt_ctf_field_put(cpu_field);
638
639 cs->cpu = cpu;
640 cs->stream = stream;
641 return cs;
642
643out:
644 if (cpu_field)
645 bt_ctf_field_put(cpu_field);
646 if (stream)
647 bt_ctf_stream_put(stream);
648
649 free(cs);
650 return NULL;
651}
652
653static void ctf_stream__delete(struct ctf_stream *cs)
654{
655 if (cs) {
656 bt_ctf_stream_put(cs->stream);
657 free(cs);
658 }
659}
660
661static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu)
662{
663 struct ctf_stream *cs = cw->stream[cpu];
664
665 if (!cs) {
666 cs = ctf_stream__create(cw, cpu);
667 cw->stream[cpu] = cs;
668 }
669
670 return cs;
671}
672
673static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample,
674 struct perf_evsel *evsel)
675{
676 int cpu = 0;
677
678 if (evsel->attr.sample_type & PERF_SAMPLE_CPU)
679 cpu = sample->cpu;
680
681 if (cpu > cw->stream_cnt) {
682 pr_err("Event was recorded for CPU %d, limit is at %d.\n",
683 cpu, cw->stream_cnt);
684 cpu = 0;
685 }
686
687 return cpu;
688}
689
Jiri Olsa89e5fa82015-04-18 17:50:16 +0200690#define STREAM_FLUSH_COUNT 100000
691
692/*
693 * Currently we have no other way to determine the
694 * time for the stream flush other than keep track
695 * of the number of events and check it against
696 * threshold.
697 */
698static bool is_flush_needed(struct ctf_stream *cs)
699{
700 return cs->count >= STREAM_FLUSH_COUNT;
701}
702
Jiri Olsaedbe9812015-02-20 23:17:00 +0100703static int process_sample_event(struct perf_tool *tool,
Arnaldo Carvalho de Melob8f8eb82016-03-22 13:09:37 -0300704 union perf_event *_event,
Jiri Olsaedbe9812015-02-20 23:17:00 +0100705 struct perf_sample *sample,
706 struct perf_evsel *evsel,
707 struct machine *machine __maybe_unused)
708{
709 struct convert *c = container_of(tool, struct convert, tool);
710 struct evsel_priv *priv = evsel->priv;
711 struct ctf_writer *cw = &c->writer;
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +0200712 struct ctf_stream *cs;
Jiri Olsaedbe9812015-02-20 23:17:00 +0100713 struct bt_ctf_event_class *event_class;
714 struct bt_ctf_event *event;
715 int ret;
716
717 if (WARN_ONCE(!priv, "Failed to setup all events.\n"))
718 return 0;
719
720 event_class = priv->event_class;
721
722 /* update stats */
723 c->events_count++;
724 c->events_size += _event->header.size;
725
726 pr_time2(sample->time, "sample %" PRIu64 "\n", c->events_count);
727
728 event = bt_ctf_event_create(event_class);
729 if (!event) {
730 pr_err("Failed to create an CTF event\n");
731 return -1;
732 }
733
734 bt_ctf_clock_set_time(cw->clock, sample->time);
735
736 ret = add_generic_values(cw, event, evsel, sample);
737 if (ret)
738 return -1;
739
Sebastian Andrzej Siewior69364722015-02-20 23:17:02 +0100740 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
741 ret = add_tracepoint_values(cw, event_class, event,
742 evsel, sample);
743 if (ret)
744 return -1;
745 }
746
Wang Nan6122d572016-02-26 09:31:56 +0000747 if (perf_evsel__is_bpf_output(evsel)) {
748 ret = add_bpf_output_values(event_class, event, sample);
749 if (ret)
750 return -1;
751 }
752
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +0200753 cs = ctf_stream(cw, get_sample_cpu(cw, sample, evsel));
Jiri Olsa89e5fa82015-04-18 17:50:16 +0200754 if (cs) {
755 if (is_flush_needed(cs))
756 ctf_stream__flush(cs);
757
758 cs->count++;
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +0200759 bt_ctf_stream_append_event(cs->stream, event);
Jiri Olsa89e5fa82015-04-18 17:50:16 +0200760 }
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +0200761
Jiri Olsaedbe9812015-02-20 23:17:00 +0100762 bt_ctf_event_put(event);
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +0200763 return cs ? 0 : -1;
Jiri Olsaedbe9812015-02-20 23:17:00 +0100764}
765
Wang Nane0a7cce2015-04-18 17:50:19 +0200766/* If dup < 0, add a prefix. Else, add _dupl_X suffix. */
767static char *change_name(char *name, char *orig_name, int dup)
768{
769 char *new_name = NULL;
770 size_t len;
771
772 if (!name)
773 name = orig_name;
774
775 if (dup >= 10)
776 goto out;
777 /*
778 * Add '_' prefix to potential keywork. According to
779 * Mathieu Desnoyers (https://lkml.org/lkml/2015/1/23/652),
780 * futher CTF spec updating may require us to use '$'.
781 */
782 if (dup < 0)
783 len = strlen(name) + sizeof("_");
784 else
785 len = strlen(orig_name) + sizeof("_dupl_X");
786
787 new_name = malloc(len);
788 if (!new_name)
789 goto out;
790
791 if (dup < 0)
792 snprintf(new_name, len, "_%s", name);
793 else
794 snprintf(new_name, len, "%s_dupl_%d", orig_name, dup);
795
796out:
797 if (name != orig_name)
798 free(name);
799 return new_name;
800}
801
802static int event_class_add_field(struct bt_ctf_event_class *event_class,
803 struct bt_ctf_field_type *type,
804 struct format_field *field)
805{
806 struct bt_ctf_field_type *t = NULL;
807 char *name;
808 int dup = 1;
809 int ret;
810
811 /* alias was already assigned */
812 if (field->alias != field->name)
813 return bt_ctf_event_class_add_field(event_class, type,
814 (char *)field->alias);
815
816 name = field->name;
817
818 /* If 'name' is a keywork, add prefix. */
819 if (bt_ctf_validate_identifier(name))
820 name = change_name(name, field->name, -1);
821
822 if (!name) {
823 pr_err("Failed to fix invalid identifier.");
824 return -1;
825 }
826 while ((t = bt_ctf_event_class_get_field_by_name(event_class, name))) {
827 bt_ctf_field_type_put(t);
828 name = change_name(name, field->name, dup++);
829 if (!name) {
830 pr_err("Failed to create dup name for '%s'\n", field->name);
831 return -1;
832 }
833 }
834
835 ret = bt_ctf_event_class_add_field(event_class, type, name);
836 if (!ret)
837 field->alias = name;
838
839 return ret;
840}
841
Sebastian Andrzej Siewior69364722015-02-20 23:17:02 +0100842static int add_tracepoint_fields_types(struct ctf_writer *cw,
843 struct format_field *fields,
844 struct bt_ctf_event_class *event_class)
845{
846 struct format_field *field;
847 int ret;
848
849 for (field = fields; field; field = field->next) {
850 struct bt_ctf_field_type *type;
851 unsigned long flags = field->flags;
852
853 pr2(" field '%s'\n", field->name);
854
855 type = get_tracepoint_field_type(cw, field);
856 if (!type)
857 return -1;
858
859 /*
860 * A string is an array of chars. For this we use the string
861 * type and don't care that it is an array. What we don't
862 * support is an array of strings.
863 */
864 if (flags & FIELD_IS_STRING)
865 flags &= ~FIELD_IS_ARRAY;
866
867 if (flags & FIELD_IS_ARRAY)
868 type = bt_ctf_field_type_array_create(type, field->arraylen);
869
Wang Nane0a7cce2015-04-18 17:50:19 +0200870 ret = event_class_add_field(event_class, type, field);
Sebastian Andrzej Siewior69364722015-02-20 23:17:02 +0100871
872 if (flags & FIELD_IS_ARRAY)
873 bt_ctf_field_type_put(type);
874
875 if (ret) {
Wang Nane0a7cce2015-04-18 17:50:19 +0200876 pr_err("Failed to add field '%s': %d\n",
877 field->name, ret);
Sebastian Andrzej Siewior69364722015-02-20 23:17:02 +0100878 return -1;
879 }
880 }
881
882 return 0;
883}
884
885static int add_tracepoint_types(struct ctf_writer *cw,
886 struct perf_evsel *evsel,
887 struct bt_ctf_event_class *class)
888{
889 struct format_field *common_fields = evsel->tp_format->format.common_fields;
890 struct format_field *fields = evsel->tp_format->format.fields;
891 int ret;
892
893 ret = add_tracepoint_fields_types(cw, common_fields, class);
894 if (!ret)
895 ret = add_tracepoint_fields_types(cw, fields, class);
896
897 return ret;
898}
899
Wang Nan6122d572016-02-26 09:31:56 +0000900static int add_bpf_output_types(struct ctf_writer *cw,
901 struct bt_ctf_event_class *class)
902{
903 struct bt_ctf_field_type *len_type = cw->data.u32;
904 struct bt_ctf_field_type *seq_base_type = cw->data.u32_hex;
905 struct bt_ctf_field_type *seq_type;
906 int ret;
907
908 ret = bt_ctf_event_class_add_field(class, len_type, "raw_len");
909 if (ret)
910 return ret;
911
912 seq_type = bt_ctf_field_type_sequence_create(seq_base_type, "raw_len");
913 if (!seq_type)
914 return -1;
915
916 return bt_ctf_event_class_add_field(class, seq_type, "raw_data");
917}
918
Jiri Olsaedbe9812015-02-20 23:17:00 +0100919static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
920 struct bt_ctf_event_class *event_class)
921{
922 u64 type = evsel->attr.sample_type;
923
924 /*
925 * missing:
926 * PERF_SAMPLE_TIME - not needed as we have it in
927 * ctf event header
928 * PERF_SAMPLE_READ - TODO
929 * PERF_SAMPLE_CALLCHAIN - TODO
Wang Nan6122d572016-02-26 09:31:56 +0000930 * PERF_SAMPLE_RAW - tracepoint fields and BPF output
931 * are handled separately
Jiri Olsaedbe9812015-02-20 23:17:00 +0100932 * PERF_SAMPLE_BRANCH_STACK - TODO
933 * PERF_SAMPLE_REGS_USER - TODO
934 * PERF_SAMPLE_STACK_USER - TODO
935 */
936
937#define ADD_FIELD(cl, t, n) \
938 do { \
939 pr2(" field '%s'\n", n); \
940 if (bt_ctf_event_class_add_field(cl, t, n)) { \
Wang Nane0a7cce2015-04-18 17:50:19 +0200941 pr_err("Failed to add field '%s';\n", n); \
Jiri Olsaedbe9812015-02-20 23:17:00 +0100942 return -1; \
943 } \
944 } while (0)
945
946 if (type & PERF_SAMPLE_IP)
Sebastian Andrzej Siewior54cf7762015-02-20 23:17:01 +0100947 ADD_FIELD(event_class, cw->data.u64_hex, "perf_ip");
Jiri Olsaedbe9812015-02-20 23:17:00 +0100948
949 if (type & PERF_SAMPLE_TID) {
Sebastian Andrzej Siewior54cf7762015-02-20 23:17:01 +0100950 ADD_FIELD(event_class, cw->data.s32, "perf_tid");
951 ADD_FIELD(event_class, cw->data.s32, "perf_pid");
Jiri Olsaedbe9812015-02-20 23:17:00 +0100952 }
953
954 if ((type & PERF_SAMPLE_ID) ||
955 (type & PERF_SAMPLE_IDENTIFIER))
Sebastian Andrzej Siewior54cf7762015-02-20 23:17:01 +0100956 ADD_FIELD(event_class, cw->data.u64, "perf_id");
Jiri Olsaedbe9812015-02-20 23:17:00 +0100957
958 if (type & PERF_SAMPLE_STREAM_ID)
Sebastian Andrzej Siewior54cf7762015-02-20 23:17:01 +0100959 ADD_FIELD(event_class, cw->data.u64, "perf_stream_id");
Jiri Olsaedbe9812015-02-20 23:17:00 +0100960
Jiri Olsaedbe9812015-02-20 23:17:00 +0100961 if (type & PERF_SAMPLE_PERIOD)
Sebastian Andrzej Siewior54cf7762015-02-20 23:17:01 +0100962 ADD_FIELD(event_class, cw->data.u64, "perf_period");
Jiri Olsaedbe9812015-02-20 23:17:00 +0100963
964 if (type & PERF_SAMPLE_WEIGHT)
Sebastian Andrzej Siewior54cf7762015-02-20 23:17:01 +0100965 ADD_FIELD(event_class, cw->data.u64, "perf_weight");
Jiri Olsaedbe9812015-02-20 23:17:00 +0100966
967 if (type & PERF_SAMPLE_DATA_SRC)
Sebastian Andrzej Siewior54cf7762015-02-20 23:17:01 +0100968 ADD_FIELD(event_class, cw->data.u64, "perf_data_src");
Jiri Olsaedbe9812015-02-20 23:17:00 +0100969
970 if (type & PERF_SAMPLE_TRANSACTION)
Sebastian Andrzej Siewior54cf7762015-02-20 23:17:01 +0100971 ADD_FIELD(event_class, cw->data.u64, "perf_transaction");
Jiri Olsaedbe9812015-02-20 23:17:00 +0100972
973#undef ADD_FIELD
974 return 0;
975}
976
977static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
978{
979 struct bt_ctf_event_class *event_class;
980 struct evsel_priv *priv;
981 const char *name = perf_evsel__name(evsel);
982 int ret;
983
984 pr("Adding event '%s' (type %d)\n", name, evsel->attr.type);
985
986 event_class = bt_ctf_event_class_create(name);
987 if (!event_class)
988 return -1;
989
990 ret = add_generic_types(cw, evsel, event_class);
991 if (ret)
992 goto err;
993
Sebastian Andrzej Siewior69364722015-02-20 23:17:02 +0100994 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
995 ret = add_tracepoint_types(cw, evsel, event_class);
996 if (ret)
997 goto err;
998 }
999
Wang Nan6122d572016-02-26 09:31:56 +00001000 if (perf_evsel__is_bpf_output(evsel)) {
1001 ret = add_bpf_output_types(cw, event_class);
1002 if (ret)
1003 goto err;
1004 }
1005
Jiri Olsaedbe9812015-02-20 23:17:00 +01001006 ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);
1007 if (ret) {
1008 pr("Failed to add event class into stream.\n");
1009 goto err;
1010 }
1011
1012 priv = malloc(sizeof(*priv));
1013 if (!priv)
1014 goto err;
1015
1016 priv->event_class = event_class;
1017 evsel->priv = priv;
1018 return 0;
1019
1020err:
1021 bt_ctf_event_class_put(event_class);
1022 pr_err("Failed to add event '%s'.\n", name);
1023 return -1;
1024}
1025
1026static int setup_events(struct ctf_writer *cw, struct perf_session *session)
1027{
1028 struct perf_evlist *evlist = session->evlist;
1029 struct perf_evsel *evsel;
1030 int ret;
1031
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03001032 evlist__for_each_entry(evlist, evsel) {
Jiri Olsaedbe9812015-02-20 23:17:00 +01001033 ret = add_event(cw, evsel);
1034 if (ret)
1035 return ret;
1036 }
1037 return 0;
1038}
1039
Wang Nan5141d732016-02-05 14:01:30 +00001040static void cleanup_events(struct perf_session *session)
1041{
1042 struct perf_evlist *evlist = session->evlist;
1043 struct perf_evsel *evsel;
1044
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03001045 evlist__for_each_entry(evlist, evsel) {
Wang Nan5141d732016-02-05 14:01:30 +00001046 struct evsel_priv *priv;
1047
1048 priv = evsel->priv;
1049 bt_ctf_event_class_put(priv->event_class);
1050 zfree(&evsel->priv);
1051 }
1052
1053 perf_evlist__delete(evlist);
1054 session->evlist = NULL;
1055}
1056
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +02001057static int setup_streams(struct ctf_writer *cw, struct perf_session *session)
1058{
1059 struct ctf_stream **stream;
1060 struct perf_header *ph = &session->header;
1061 int ncpus;
1062
1063 /*
1064 * Try to get the number of cpus used in the data file,
1065 * if not present fallback to the MAX_CPUS.
1066 */
1067 ncpus = ph->env.nr_cpus_avail ?: MAX_CPUS;
1068
1069 stream = zalloc(sizeof(*stream) * ncpus);
1070 if (!stream) {
1071 pr_err("Failed to allocate streams.\n");
1072 return -ENOMEM;
1073 }
1074
1075 cw->stream = stream;
1076 cw->stream_cnt = ncpus;
1077 return 0;
1078}
1079
1080static void free_streams(struct ctf_writer *cw)
1081{
1082 int cpu;
1083
1084 for (cpu = 0; cpu < cw->stream_cnt; cpu++)
1085 ctf_stream__delete(cw->stream[cpu]);
1086
1087 free(cw->stream);
1088}
1089
Jiri Olsaedbe9812015-02-20 23:17:00 +01001090static int ctf_writer__setup_env(struct ctf_writer *cw,
1091 struct perf_session *session)
1092{
1093 struct perf_header *header = &session->header;
1094 struct bt_ctf_writer *writer = cw->writer;
1095
1096#define ADD(__n, __v) \
1097do { \
1098 if (bt_ctf_writer_add_environment_field(writer, __n, __v)) \
1099 return -1; \
1100} while (0)
1101
1102 ADD("host", header->env.hostname);
1103 ADD("sysname", "Linux");
1104 ADD("release", header->env.os_release);
1105 ADD("version", header->env.version);
1106 ADD("machine", header->env.arch);
1107 ADD("domain", "kernel");
1108 ADD("tracer_name", "perf");
1109
1110#undef ADD
1111 return 0;
1112}
1113
1114static int ctf_writer__setup_clock(struct ctf_writer *cw)
1115{
1116 struct bt_ctf_clock *clock = cw->clock;
1117
1118 bt_ctf_clock_set_description(clock, "perf clock");
1119
1120#define SET(__n, __v) \
1121do { \
1122 if (bt_ctf_clock_set_##__n(clock, __v)) \
1123 return -1; \
1124} while (0)
1125
1126 SET(frequency, 1000000000);
1127 SET(offset_s, 0);
1128 SET(offset, 0);
1129 SET(precision, 10);
1130 SET(is_absolute, 0);
1131
1132#undef SET
1133 return 0;
1134}
1135
1136static struct bt_ctf_field_type *create_int_type(int size, bool sign, bool hex)
1137{
1138 struct bt_ctf_field_type *type;
1139
1140 type = bt_ctf_field_type_integer_create(size);
1141 if (!type)
1142 return NULL;
1143
1144 if (sign &&
1145 bt_ctf_field_type_integer_set_signed(type, 1))
1146 goto err;
1147
1148 if (hex &&
1149 bt_ctf_field_type_integer_set_base(type, BT_CTF_INTEGER_BASE_HEXADECIMAL))
1150 goto err;
1151
Wang Nanf8dd2d52016-02-26 09:31:57 +00001152#if __BYTE_ORDER == __BIG_ENDIAN
1153 bt_ctf_field_type_set_byte_order(type, BT_CTF_BYTE_ORDER_BIG_ENDIAN);
1154#else
1155 bt_ctf_field_type_set_byte_order(type, BT_CTF_BYTE_ORDER_LITTLE_ENDIAN);
1156#endif
1157
Jiri Olsaedbe9812015-02-20 23:17:00 +01001158 pr2("Created type: INTEGER %d-bit %ssigned %s\n",
1159 size, sign ? "un" : "", hex ? "hex" : "");
1160 return type;
1161
1162err:
1163 bt_ctf_field_type_put(type);
1164 return NULL;
1165}
1166
1167static void ctf_writer__cleanup_data(struct ctf_writer *cw)
1168{
1169 unsigned int i;
1170
1171 for (i = 0; i < ARRAY_SIZE(cw->data.array); i++)
1172 bt_ctf_field_type_put(cw->data.array[i]);
1173}
1174
1175static int ctf_writer__init_data(struct ctf_writer *cw)
1176{
1177#define CREATE_INT_TYPE(type, size, sign, hex) \
1178do { \
1179 (type) = create_int_type(size, sign, hex); \
1180 if (!(type)) \
1181 goto err; \
1182} while (0)
1183
1184 CREATE_INT_TYPE(cw->data.s64, 64, true, false);
1185 CREATE_INT_TYPE(cw->data.u64, 64, false, false);
1186 CREATE_INT_TYPE(cw->data.s32, 32, true, false);
1187 CREATE_INT_TYPE(cw->data.u32, 32, false, false);
Wang Nan26812d42015-12-08 02:25:39 +00001188 CREATE_INT_TYPE(cw->data.u32_hex, 32, false, true);
Jiri Olsaedbe9812015-02-20 23:17:00 +01001189 CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true);
1190
1191 cw->data.string = bt_ctf_field_type_string_create();
1192 if (cw->data.string)
1193 return 0;
1194
1195err:
1196 ctf_writer__cleanup_data(cw);
1197 pr_err("Failed to create data types.\n");
1198 return -1;
1199}
1200
1201static void ctf_writer__cleanup(struct ctf_writer *cw)
1202{
1203 ctf_writer__cleanup_data(cw);
1204
1205 bt_ctf_clock_put(cw->clock);
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +02001206 free_streams(cw);
Jiri Olsaedbe9812015-02-20 23:17:00 +01001207 bt_ctf_stream_class_put(cw->stream_class);
1208 bt_ctf_writer_put(cw->writer);
1209
1210 /* and NULL all the pointers */
1211 memset(cw, 0, sizeof(*cw));
1212}
1213
1214static int ctf_writer__init(struct ctf_writer *cw, const char *path)
1215{
1216 struct bt_ctf_writer *writer;
1217 struct bt_ctf_stream_class *stream_class;
Jiri Olsaedbe9812015-02-20 23:17:00 +01001218 struct bt_ctf_clock *clock;
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +02001219 struct bt_ctf_field_type *pkt_ctx_type;
1220 int ret;
Jiri Olsaedbe9812015-02-20 23:17:00 +01001221
1222 /* CTF writer */
1223 writer = bt_ctf_writer_create(path);
1224 if (!writer)
1225 goto err;
1226
1227 cw->writer = writer;
1228
1229 /* CTF clock */
1230 clock = bt_ctf_clock_create("perf_clock");
1231 if (!clock) {
1232 pr("Failed to create CTF clock.\n");
1233 goto err_cleanup;
1234 }
1235
1236 cw->clock = clock;
1237
1238 if (ctf_writer__setup_clock(cw)) {
1239 pr("Failed to setup CTF clock.\n");
1240 goto err_cleanup;
1241 }
1242
1243 /* CTF stream class */
1244 stream_class = bt_ctf_stream_class_create("perf_stream");
1245 if (!stream_class) {
1246 pr("Failed to create CTF stream class.\n");
1247 goto err_cleanup;
1248 }
1249
1250 cw->stream_class = stream_class;
1251
1252 /* CTF clock stream setup */
1253 if (bt_ctf_stream_class_set_clock(stream_class, clock)) {
1254 pr("Failed to assign CTF clock to stream class.\n");
1255 goto err_cleanup;
1256 }
1257
1258 if (ctf_writer__init_data(cw))
1259 goto err_cleanup;
1260
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +02001261 /* Add cpu_id for packet context */
1262 pkt_ctx_type = bt_ctf_stream_class_get_packet_context_type(stream_class);
1263 if (!pkt_ctx_type)
Jiri Olsaedbe9812015-02-20 23:17:00 +01001264 goto err_cleanup;
Jiri Olsaedbe9812015-02-20 23:17:00 +01001265
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +02001266 ret = bt_ctf_field_type_structure_add_field(pkt_ctx_type, cw->data.u32, "cpu_id");
1267 bt_ctf_field_type_put(pkt_ctx_type);
1268 if (ret)
1269 goto err_cleanup;
Jiri Olsaedbe9812015-02-20 23:17:00 +01001270
1271 /* CTF clock writer setup */
1272 if (bt_ctf_writer_add_clock(writer, clock)) {
1273 pr("Failed to assign CTF clock to writer.\n");
1274 goto err_cleanup;
1275 }
1276
1277 return 0;
1278
1279err_cleanup:
1280 ctf_writer__cleanup(cw);
1281err:
1282 pr_err("Failed to setup CTF writer.\n");
1283 return -1;
1284}
1285
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +02001286static int ctf_writer__flush_streams(struct ctf_writer *cw)
1287{
1288 int cpu, ret = 0;
1289
1290 for (cpu = 0; cpu < cw->stream_cnt && !ret; cpu++)
1291 ret = ctf_stream__flush(cw->stream[cpu]);
1292
1293 return ret;
1294}
1295
Jiri Olsa8fa46752015-04-18 17:50:17 +02001296static int convert__config(const char *var, const char *value, void *cb)
1297{
1298 struct convert *c = cb;
1299
1300 if (!strcmp(var, "convert.queue-size")) {
1301 c->queue_size = perf_config_u64(var, value);
1302 return 0;
1303 }
1304
Wang Nanb8cbb342016-02-26 09:31:51 +00001305 return 0;
Jiri Olsa8fa46752015-04-18 17:50:17 +02001306}
1307
Wang Nan3275f682016-06-24 11:22:07 +00001308int bt_convert__perf2ctf(const char *input, const char *path,
1309 struct perf_data_convert_opts *opts)
Jiri Olsaedbe9812015-02-20 23:17:00 +01001310{
1311 struct perf_session *session;
1312 struct perf_data_file file = {
1313 .path = input,
1314 .mode = PERF_DATA_MODE_READ,
Wang Nan3275f682016-06-24 11:22:07 +00001315 .force = opts->force,
Jiri Olsaedbe9812015-02-20 23:17:00 +01001316 };
1317 struct convert c = {
1318 .tool = {
1319 .sample = process_sample_event,
1320 .mmap = perf_event__process_mmap,
1321 .mmap2 = perf_event__process_mmap2,
1322 .comm = perf_event__process_comm,
1323 .exit = perf_event__process_exit,
1324 .fork = perf_event__process_fork,
1325 .lost = perf_event__process_lost,
1326 .tracing_data = perf_event__process_tracing_data,
1327 .build_id = perf_event__process_build_id,
1328 .ordered_events = true,
1329 .ordering_requires_timestamps = true,
1330 },
1331 };
1332 struct ctf_writer *cw = &c.writer;
1333 int err = -1;
1334
Jiri Olsa8fa46752015-04-18 17:50:17 +02001335 perf_config(convert__config, &c);
1336
Jiri Olsaedbe9812015-02-20 23:17:00 +01001337 /* CTF writer */
1338 if (ctf_writer__init(cw, path))
1339 return -1;
1340
1341 /* perf.data session */
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -03001342 session = perf_session__new(&file, 0, &c.tool);
Jiri Olsaedbe9812015-02-20 23:17:00 +01001343 if (!session)
1344 goto free_writer;
1345
Jiri Olsa8fa46752015-04-18 17:50:17 +02001346 if (c.queue_size) {
1347 ordered_events__set_alloc_size(&session->ordered_events,
1348 c.queue_size);
1349 }
1350
Jiri Olsaedbe9812015-02-20 23:17:00 +01001351 /* CTF writer env/clock setup */
1352 if (ctf_writer__setup_env(cw, session))
1353 goto free_session;
1354
1355 /* CTF events setup */
1356 if (setup_events(cw, session))
1357 goto free_session;
1358
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +02001359 if (setup_streams(cw, session))
1360 goto free_session;
1361
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -03001362 err = perf_session__process_events(session);
Jiri Olsaedbe9812015-02-20 23:17:00 +01001363 if (!err)
Sebastian Andrzej Siewior90e129f2015-04-18 17:50:15 +02001364 err = ctf_writer__flush_streams(cw);
He Kuangc2141052015-04-18 17:50:14 +02001365 else
1366 pr_err("Error during conversion.\n");
Jiri Olsaedbe9812015-02-20 23:17:00 +01001367
1368 fprintf(stderr,
1369 "[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
1370 file.path, path);
1371
1372 fprintf(stderr,
Wang Nan8ee4c462016-06-24 11:22:09 +00001373 "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
Jiri Olsaedbe9812015-02-20 23:17:00 +01001374 (double) c.events_size / 1024.0 / 1024.0,
1375 c.events_count);
1376
Wang Nan8ee4c462016-06-24 11:22:09 +00001377 if (!c.non_sample_count)
1378 fprintf(stderr, ") ]\n");
1379 else
1380 fprintf(stderr, ", %" PRIu64 " non-samples) ]\n", c.non_sample_count);
1381
Wang Nan5141d732016-02-05 14:01:30 +00001382 cleanup_events(session);
He Kuangc2141052015-04-18 17:50:14 +02001383 perf_session__delete(session);
1384 ctf_writer__cleanup(cw);
1385
1386 return err;
1387
Jiri Olsaedbe9812015-02-20 23:17:00 +01001388free_session:
1389 perf_session__delete(session);
Jiri Olsaedbe9812015-02-20 23:17:00 +01001390free_writer:
1391 ctf_writer__cleanup(cw);
He Kuangc2141052015-04-18 17:50:14 +02001392 pr_err("Error during conversion setup.\n");
Jiri Olsaedbe9812015-02-20 23:17:00 +01001393 return err;
1394}