xref: /linux/tools/perf/util/data-convert-bt.c (revision f5a08ceda55bee91f879d2ac19edeb4a8916d04f)
1edbe9817SJiri Olsa /*
2edbe9817SJiri Olsa  * CTF writing support via babeltrace.
3edbe9817SJiri Olsa  *
4edbe9817SJiri Olsa  * Copyright (C) 2014, Jiri Olsa <jolsa@redhat.com>
5edbe9817SJiri Olsa  * Copyright (C) 2014, Sebastian Andrzej Siewior <bigeasy@linutronix.de>
6edbe9817SJiri Olsa  *
7edbe9817SJiri Olsa  * Released under the GPL v2. (and only v2, not any later version)
8edbe9817SJiri Olsa  */
9edbe9817SJiri Olsa 
10edbe9817SJiri Olsa #include <linux/compiler.h>
11edbe9817SJiri Olsa #include <babeltrace/ctf-writer/writer.h>
12edbe9817SJiri Olsa #include <babeltrace/ctf-writer/clock.h>
13edbe9817SJiri Olsa #include <babeltrace/ctf-writer/stream.h>
14edbe9817SJiri Olsa #include <babeltrace/ctf-writer/event.h>
15edbe9817SJiri Olsa #include <babeltrace/ctf-writer/event-types.h>
16edbe9817SJiri Olsa #include <babeltrace/ctf-writer/event-fields.h>
17e0a7cce5SWang Nan #include <babeltrace/ctf-ir/utils.h>
18edbe9817SJiri Olsa #include <babeltrace/ctf/events.h>
19edbe9817SJiri Olsa #include <traceevent/event-parse.h>
20edbe9817SJiri Olsa #include "asm/bug.h"
21edbe9817SJiri Olsa #include "data-convert-bt.h"
22edbe9817SJiri Olsa #include "session.h"
23edbe9817SJiri Olsa #include "util.h"
24edbe9817SJiri Olsa #include "debug.h"
25edbe9817SJiri Olsa #include "tool.h"
26edbe9817SJiri Olsa #include "evlist.h"
27edbe9817SJiri Olsa #include "evsel.h"
28edbe9817SJiri Olsa #include "machine.h"
29f6c12a00SJiri Olsa #include "config.h"
30edbe9817SJiri Olsa 
31edbe9817SJiri Olsa #define pr_N(n, fmt, ...) \
32edbe9817SJiri Olsa 	eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
33edbe9817SJiri Olsa 
34edbe9817SJiri Olsa #define pr(fmt, ...)  pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
35edbe9817SJiri Olsa #define pr2(fmt, ...) pr_N(2, pr_fmt(fmt), ##__VA_ARGS__)
36edbe9817SJiri Olsa 
37edbe9817SJiri Olsa #define pr_time2(t, fmt, ...) pr_time_N(2, debug_data_convert, t, pr_fmt(fmt), ##__VA_ARGS__)
38edbe9817SJiri Olsa 
39edbe9817SJiri Olsa struct evsel_priv {
40edbe9817SJiri Olsa 	struct bt_ctf_event_class *event_class;
41edbe9817SJiri Olsa };
42edbe9817SJiri Olsa 
4390e129ffSSebastian Andrzej Siewior #define MAX_CPUS	4096
4490e129ffSSebastian Andrzej Siewior 
4590e129ffSSebastian Andrzej Siewior struct ctf_stream {
4690e129ffSSebastian Andrzej Siewior 	struct bt_ctf_stream *stream;
4790e129ffSSebastian Andrzej Siewior 	int cpu;
4889e5fa88SJiri Olsa 	u32 count;
4990e129ffSSebastian Andrzej Siewior };
5090e129ffSSebastian Andrzej Siewior 
51edbe9817SJiri Olsa struct ctf_writer {
52edbe9817SJiri Olsa 	/* writer primitives */
53edbe9817SJiri Olsa 	struct bt_ctf_writer		 *writer;
5490e129ffSSebastian Andrzej Siewior 	struct ctf_stream		**stream;
5590e129ffSSebastian Andrzej Siewior 	int				  stream_cnt;
56edbe9817SJiri Olsa 	struct bt_ctf_stream_class	 *stream_class;
57edbe9817SJiri Olsa 	struct bt_ctf_clock		 *clock;
58edbe9817SJiri Olsa 
59edbe9817SJiri Olsa 	/* data types */
60edbe9817SJiri Olsa 	union {
61edbe9817SJiri Olsa 		struct {
62edbe9817SJiri Olsa 			struct bt_ctf_field_type	*s64;
63edbe9817SJiri Olsa 			struct bt_ctf_field_type	*u64;
64edbe9817SJiri Olsa 			struct bt_ctf_field_type	*s32;
65edbe9817SJiri Olsa 			struct bt_ctf_field_type	*u32;
66edbe9817SJiri Olsa 			struct bt_ctf_field_type	*string;
6726812d46SWang Nan 			struct bt_ctf_field_type	*u32_hex;
68edbe9817SJiri Olsa 			struct bt_ctf_field_type	*u64_hex;
69edbe9817SJiri Olsa 		};
70edbe9817SJiri Olsa 		struct bt_ctf_field_type *array[6];
71edbe9817SJiri Olsa 	} data;
72*f5a08cedSWang Nan 	struct bt_ctf_event_class	*comm_class;
73edbe9817SJiri Olsa };
74edbe9817SJiri Olsa 
75edbe9817SJiri Olsa struct convert {
76edbe9817SJiri Olsa 	struct perf_tool	tool;
77edbe9817SJiri Olsa 	struct ctf_writer	writer;
78edbe9817SJiri Olsa 
79edbe9817SJiri Olsa 	u64			events_size;
80edbe9817SJiri Olsa 	u64			events_count;
818ee4c46cSWang Nan 	u64			non_sample_count;
828fa46753SJiri Olsa 
838fa46753SJiri Olsa 	/* Ordered events configured queue size. */
848fa46753SJiri Olsa 	u64			queue_size;
85edbe9817SJiri Olsa };
86edbe9817SJiri Olsa 
87edbe9817SJiri Olsa static int value_set(struct bt_ctf_field_type *type,
88edbe9817SJiri Olsa 		     struct bt_ctf_event *event,
89edbe9817SJiri Olsa 		     const char *name, u64 val)
90edbe9817SJiri Olsa {
91edbe9817SJiri Olsa 	struct bt_ctf_field *field;
92edbe9817SJiri Olsa 	bool sign = bt_ctf_field_type_integer_get_signed(type);
93edbe9817SJiri Olsa 	int ret;
94edbe9817SJiri Olsa 
95edbe9817SJiri Olsa 	field = bt_ctf_field_create(type);
96edbe9817SJiri Olsa 	if (!field) {
97edbe9817SJiri Olsa 		pr_err("failed to create a field %s\n", name);
98edbe9817SJiri Olsa 		return -1;
99edbe9817SJiri Olsa 	}
100edbe9817SJiri Olsa 
101edbe9817SJiri Olsa 	if (sign) {
102edbe9817SJiri Olsa 		ret = bt_ctf_field_signed_integer_set_value(field, val);
103edbe9817SJiri Olsa 		if (ret) {
104edbe9817SJiri Olsa 			pr_err("failed to set field value %s\n", name);
105edbe9817SJiri Olsa 			goto err;
106edbe9817SJiri Olsa 		}
107edbe9817SJiri Olsa 	} else {
108edbe9817SJiri Olsa 		ret = bt_ctf_field_unsigned_integer_set_value(field, val);
109edbe9817SJiri Olsa 		if (ret) {
110edbe9817SJiri Olsa 			pr_err("failed to set field value %s\n", name);
111edbe9817SJiri Olsa 			goto err;
112edbe9817SJiri Olsa 		}
113edbe9817SJiri Olsa 	}
114edbe9817SJiri Olsa 
115edbe9817SJiri Olsa 	ret = bt_ctf_event_set_payload(event, name, field);
116edbe9817SJiri Olsa 	if (ret) {
117edbe9817SJiri Olsa 		pr_err("failed to set payload %s\n", name);
118edbe9817SJiri Olsa 		goto err;
119edbe9817SJiri Olsa 	}
120edbe9817SJiri Olsa 
121edbe9817SJiri Olsa 	pr2("  SET [%s = %" PRIu64 "]\n", name, val);
122edbe9817SJiri Olsa 
123edbe9817SJiri Olsa err:
124edbe9817SJiri Olsa 	bt_ctf_field_put(field);
125edbe9817SJiri Olsa 	return ret;
126edbe9817SJiri Olsa }
127edbe9817SJiri Olsa 
128edbe9817SJiri Olsa #define __FUNC_VALUE_SET(_name, _val_type)				\
129edbe9817SJiri Olsa static __maybe_unused int value_set_##_name(struct ctf_writer *cw,	\
130edbe9817SJiri Olsa 			     struct bt_ctf_event *event,		\
131edbe9817SJiri Olsa 			     const char *name,				\
132edbe9817SJiri Olsa 			     _val_type val)				\
133edbe9817SJiri Olsa {									\
134edbe9817SJiri Olsa 	struct bt_ctf_field_type *type = cw->data._name;		\
135edbe9817SJiri Olsa 	return value_set(type, event, name, (u64) val);			\
136edbe9817SJiri Olsa }
137edbe9817SJiri Olsa 
138edbe9817SJiri Olsa #define FUNC_VALUE_SET(_name) __FUNC_VALUE_SET(_name, _name)
139edbe9817SJiri Olsa 
140edbe9817SJiri Olsa FUNC_VALUE_SET(s32)
141edbe9817SJiri Olsa FUNC_VALUE_SET(u32)
142edbe9817SJiri Olsa FUNC_VALUE_SET(s64)
143edbe9817SJiri Olsa FUNC_VALUE_SET(u64)
144edbe9817SJiri Olsa __FUNC_VALUE_SET(u64_hex, u64)
145edbe9817SJiri Olsa 
146069ee5c4SWang Nan static int string_set_value(struct bt_ctf_field *field, const char *string);
147069ee5c4SWang Nan static __maybe_unused int
148069ee5c4SWang Nan value_set_string(struct ctf_writer *cw, struct bt_ctf_event *event,
149069ee5c4SWang Nan 		 const char *name, const char *string)
150069ee5c4SWang Nan {
151069ee5c4SWang Nan 	struct bt_ctf_field_type *type = cw->data.string;
152069ee5c4SWang Nan 	struct bt_ctf_field *field;
153069ee5c4SWang Nan 	int ret = 0;
154069ee5c4SWang Nan 
155069ee5c4SWang Nan 	field = bt_ctf_field_create(type);
156069ee5c4SWang Nan 	if (!field) {
157069ee5c4SWang Nan 		pr_err("failed to create a field %s\n", name);
158069ee5c4SWang Nan 		return -1;
159069ee5c4SWang Nan 	}
160069ee5c4SWang Nan 
161069ee5c4SWang Nan 	ret = string_set_value(field, string);
162069ee5c4SWang Nan 	if (ret) {
163069ee5c4SWang Nan 		pr_err("failed to set value %s\n", name);
164069ee5c4SWang Nan 		goto err_put_field;
165069ee5c4SWang Nan 	}
166069ee5c4SWang Nan 
167069ee5c4SWang Nan 	ret = bt_ctf_event_set_payload(event, name, field);
168069ee5c4SWang Nan 	if (ret)
169069ee5c4SWang Nan 		pr_err("failed to set payload %s\n", name);
170069ee5c4SWang Nan 
171069ee5c4SWang Nan err_put_field:
172069ee5c4SWang Nan 	bt_ctf_field_put(field);
173069ee5c4SWang Nan 	return ret;
174069ee5c4SWang Nan }
175069ee5c4SWang Nan 
17669364727SSebastian Andrzej Siewior static struct bt_ctf_field_type*
17769364727SSebastian Andrzej Siewior get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
17869364727SSebastian Andrzej Siewior {
17969364727SSebastian Andrzej Siewior 	unsigned long flags = field->flags;
18069364727SSebastian Andrzej Siewior 
18169364727SSebastian Andrzej Siewior 	if (flags & FIELD_IS_STRING)
18269364727SSebastian Andrzej Siewior 		return cw->data.string;
18369364727SSebastian Andrzej Siewior 
18469364727SSebastian Andrzej Siewior 	if (!(flags & FIELD_IS_SIGNED)) {
18569364727SSebastian Andrzej Siewior 		/* unsigned long are mostly pointers */
18669364727SSebastian Andrzej Siewior 		if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER)
18769364727SSebastian Andrzej Siewior 			return cw->data.u64_hex;
18869364727SSebastian Andrzej Siewior 	}
18969364727SSebastian Andrzej Siewior 
19069364727SSebastian Andrzej Siewior 	if (flags & FIELD_IS_SIGNED) {
19169364727SSebastian Andrzej Siewior 		if (field->size == 8)
19269364727SSebastian Andrzej Siewior 			return cw->data.s64;
19369364727SSebastian Andrzej Siewior 		else
19469364727SSebastian Andrzej Siewior 			return cw->data.s32;
19569364727SSebastian Andrzej Siewior 	}
19669364727SSebastian Andrzej Siewior 
19769364727SSebastian Andrzej Siewior 	if (field->size == 8)
19869364727SSebastian Andrzej Siewior 		return cw->data.u64;
19969364727SSebastian Andrzej Siewior 	else
20069364727SSebastian Andrzej Siewior 		return cw->data.u32;
20169364727SSebastian Andrzej Siewior }
20269364727SSebastian Andrzej Siewior 
203d4ae4213SWang Nan static unsigned long long adjust_signedness(unsigned long long value_int, int size)
204d4ae4213SWang Nan {
205d4ae4213SWang Nan 	unsigned long long value_mask;
206d4ae4213SWang Nan 
207d4ae4213SWang Nan 	/*
208d4ae4213SWang Nan 	 * value_mask = (1 << (size * 8 - 1)) - 1.
209d4ae4213SWang Nan 	 * Directly set value_mask for code readers.
210d4ae4213SWang Nan 	 */
211d4ae4213SWang Nan 	switch (size) {
212d4ae4213SWang Nan 	case 1:
213d4ae4213SWang Nan 		value_mask = 0x7fULL;
214d4ae4213SWang Nan 		break;
215d4ae4213SWang Nan 	case 2:
216d4ae4213SWang Nan 		value_mask = 0x7fffULL;
217d4ae4213SWang Nan 		break;
218d4ae4213SWang Nan 	case 4:
219d4ae4213SWang Nan 		value_mask = 0x7fffffffULL;
220d4ae4213SWang Nan 		break;
221d4ae4213SWang Nan 	case 8:
222d4ae4213SWang Nan 		/*
223d4ae4213SWang Nan 		 * For 64 bit value, return it self. There is no need
224d4ae4213SWang Nan 		 * to fill high bit.
225d4ae4213SWang Nan 		 */
226d4ae4213SWang Nan 		/* Fall through */
227d4ae4213SWang Nan 	default:
228d4ae4213SWang Nan 		/* BUG! */
229d4ae4213SWang Nan 		return value_int;
230d4ae4213SWang Nan 	}
231d4ae4213SWang Nan 
232d4ae4213SWang Nan 	/* If it is a positive value, don't adjust. */
233d4ae4213SWang Nan 	if ((value_int & (~0ULL - value_mask)) == 0)
234d4ae4213SWang Nan 		return value_int;
235d4ae4213SWang Nan 
236d4ae4213SWang Nan 	/* Fill upper part of value_int with 1 to make it a negative long long. */
237d4ae4213SWang Nan 	return (value_int & value_mask) | ~value_mask;
238d4ae4213SWang Nan }
239d4ae4213SWang Nan 
2405ea5888bSWang Nan static int string_set_value(struct bt_ctf_field *field, const char *string)
2415ea5888bSWang Nan {
2425ea5888bSWang Nan 	char *buffer = NULL;
2435ea5888bSWang Nan 	size_t len = strlen(string), i, p;
2445ea5888bSWang Nan 	int err;
2455ea5888bSWang Nan 
2465ea5888bSWang Nan 	for (i = p = 0; i < len; i++, p++) {
2475ea5888bSWang Nan 		if (isprint(string[i])) {
2485ea5888bSWang Nan 			if (!buffer)
2495ea5888bSWang Nan 				continue;
2505ea5888bSWang Nan 			buffer[p] = string[i];
2515ea5888bSWang Nan 		} else {
2525ea5888bSWang Nan 			char numstr[5];
2535ea5888bSWang Nan 
2545ea5888bSWang Nan 			snprintf(numstr, sizeof(numstr), "\\x%02x",
2555ea5888bSWang Nan 				 (unsigned int)(string[i]) & 0xff);
2565ea5888bSWang Nan 
2575ea5888bSWang Nan 			if (!buffer) {
2585ea5888bSWang Nan 				buffer = zalloc(i + (len - i) * 4 + 2);
2595ea5888bSWang Nan 				if (!buffer) {
2605ea5888bSWang Nan 					pr_err("failed to set unprintable string '%s'\n", string);
2615ea5888bSWang Nan 					return bt_ctf_field_string_set_value(field, "UNPRINTABLE-STRING");
2625ea5888bSWang Nan 				}
2635ea5888bSWang Nan 				if (i > 0)
2645ea5888bSWang Nan 					strncpy(buffer, string, i);
2655ea5888bSWang Nan 			}
2665ea5888bSWang Nan 			strncat(buffer + p, numstr, 4);
2675ea5888bSWang Nan 			p += 3;
2685ea5888bSWang Nan 		}
2695ea5888bSWang Nan 	}
2705ea5888bSWang Nan 
2715ea5888bSWang Nan 	if (!buffer)
2725ea5888bSWang Nan 		return bt_ctf_field_string_set_value(field, string);
2735ea5888bSWang Nan 	err = bt_ctf_field_string_set_value(field, buffer);
2745ea5888bSWang Nan 	free(buffer);
2755ea5888bSWang Nan 	return err;
2765ea5888bSWang Nan }
2775ea5888bSWang Nan 
27869364727SSebastian Andrzej Siewior static int add_tracepoint_field_value(struct ctf_writer *cw,
27969364727SSebastian Andrzej Siewior 				      struct bt_ctf_event_class *event_class,
28069364727SSebastian Andrzej Siewior 				      struct bt_ctf_event *event,
28169364727SSebastian Andrzej Siewior 				      struct perf_sample *sample,
28269364727SSebastian Andrzej Siewior 				      struct format_field *fmtf)
28369364727SSebastian Andrzej Siewior {
28469364727SSebastian Andrzej Siewior 	struct bt_ctf_field_type *type;
28569364727SSebastian Andrzej Siewior 	struct bt_ctf_field *array_field;
28669364727SSebastian Andrzej Siewior 	struct bt_ctf_field *field;
28769364727SSebastian Andrzej Siewior 	const char *name = fmtf->name;
28869364727SSebastian Andrzej Siewior 	void *data = sample->raw_data;
28969364727SSebastian Andrzej Siewior 	unsigned long flags = fmtf->flags;
29069364727SSebastian Andrzej Siewior 	unsigned int n_items;
29169364727SSebastian Andrzej Siewior 	unsigned int i;
29269364727SSebastian Andrzej Siewior 	unsigned int offset;
29369364727SSebastian Andrzej Siewior 	unsigned int len;
29469364727SSebastian Andrzej Siewior 	int ret;
29569364727SSebastian Andrzej Siewior 
296e0a7cce5SWang Nan 	name = fmtf->alias;
29769364727SSebastian Andrzej Siewior 	offset = fmtf->offset;
29869364727SSebastian Andrzej Siewior 	len = fmtf->size;
29969364727SSebastian Andrzej Siewior 	if (flags & FIELD_IS_STRING)
30069364727SSebastian Andrzej Siewior 		flags &= ~FIELD_IS_ARRAY;
30169364727SSebastian Andrzej Siewior 
30269364727SSebastian Andrzej Siewior 	if (flags & FIELD_IS_DYNAMIC) {
30369364727SSebastian Andrzej Siewior 		unsigned long long tmp_val;
30469364727SSebastian Andrzej Siewior 
30569364727SSebastian Andrzej Siewior 		tmp_val = pevent_read_number(fmtf->event->pevent,
30669364727SSebastian Andrzej Siewior 				data + offset, len);
30769364727SSebastian Andrzej Siewior 		offset = tmp_val;
30869364727SSebastian Andrzej Siewior 		len = offset >> 16;
30969364727SSebastian Andrzej Siewior 		offset &= 0xffff;
31069364727SSebastian Andrzej Siewior 	}
31169364727SSebastian Andrzej Siewior 
31269364727SSebastian Andrzej Siewior 	if (flags & FIELD_IS_ARRAY) {
31369364727SSebastian Andrzej Siewior 
31469364727SSebastian Andrzej Siewior 		type = bt_ctf_event_class_get_field_by_name(
31569364727SSebastian Andrzej Siewior 				event_class, name);
31669364727SSebastian Andrzej Siewior 		array_field = bt_ctf_field_create(type);
31769364727SSebastian Andrzej Siewior 		bt_ctf_field_type_put(type);
31869364727SSebastian Andrzej Siewior 		if (!array_field) {
31969364727SSebastian Andrzej Siewior 			pr_err("Failed to create array type %s\n", name);
32069364727SSebastian Andrzej Siewior 			return -1;
32169364727SSebastian Andrzej Siewior 		}
32269364727SSebastian Andrzej Siewior 
32369364727SSebastian Andrzej Siewior 		len = fmtf->size / fmtf->arraylen;
32469364727SSebastian Andrzej Siewior 		n_items = fmtf->arraylen;
32569364727SSebastian Andrzej Siewior 	} else {
32669364727SSebastian Andrzej Siewior 		n_items = 1;
32769364727SSebastian Andrzej Siewior 		array_field = NULL;
32869364727SSebastian Andrzej Siewior 	}
32969364727SSebastian Andrzej Siewior 
33069364727SSebastian Andrzej Siewior 	type = get_tracepoint_field_type(cw, fmtf);
33169364727SSebastian Andrzej Siewior 
33269364727SSebastian Andrzej Siewior 	for (i = 0; i < n_items; i++) {
33369364727SSebastian Andrzej Siewior 		if (flags & FIELD_IS_ARRAY)
33469364727SSebastian Andrzej Siewior 			field = bt_ctf_field_array_get_field(array_field, i);
33569364727SSebastian Andrzej Siewior 		else
33669364727SSebastian Andrzej Siewior 			field = bt_ctf_field_create(type);
33769364727SSebastian Andrzej Siewior 
33869364727SSebastian Andrzej Siewior 		if (!field) {
33969364727SSebastian Andrzej Siewior 			pr_err("failed to create a field %s\n", name);
34069364727SSebastian Andrzej Siewior 			return -1;
34169364727SSebastian Andrzej Siewior 		}
34269364727SSebastian Andrzej Siewior 
34369364727SSebastian Andrzej Siewior 		if (flags & FIELD_IS_STRING)
3445ea5888bSWang Nan 			ret = string_set_value(field, data + offset + i * len);
345d4ae4213SWang Nan 		else {
346d4ae4213SWang Nan 			unsigned long long value_int;
347d4ae4213SWang Nan 
348d4ae4213SWang Nan 			value_int = pevent_read_number(
349d4ae4213SWang Nan 					fmtf->event->pevent,
350d4ae4213SWang Nan 					data + offset + i * len, len);
351d4ae4213SWang Nan 
352d4ae4213SWang Nan 			if (!(flags & FIELD_IS_SIGNED))
35369364727SSebastian Andrzej Siewior 				ret = bt_ctf_field_unsigned_integer_set_value(
35469364727SSebastian Andrzej Siewior 						field, value_int);
35569364727SSebastian Andrzej Siewior 			else
35669364727SSebastian Andrzej Siewior 				ret = bt_ctf_field_signed_integer_set_value(
357d4ae4213SWang Nan 						field, adjust_signedness(value_int, len));
358d4ae4213SWang Nan 		}
359d4ae4213SWang Nan 
36069364727SSebastian Andrzej Siewior 		if (ret) {
36169364727SSebastian Andrzej Siewior 			pr_err("failed to set file value %s\n", name);
36269364727SSebastian Andrzej Siewior 			goto err_put_field;
36369364727SSebastian Andrzej Siewior 		}
36469364727SSebastian Andrzej Siewior 		if (!(flags & FIELD_IS_ARRAY)) {
36569364727SSebastian Andrzej Siewior 			ret = bt_ctf_event_set_payload(event, name, field);
36669364727SSebastian Andrzej Siewior 			if (ret) {
36769364727SSebastian Andrzej Siewior 				pr_err("failed to set payload %s\n", name);
36869364727SSebastian Andrzej Siewior 				goto err_put_field;
36969364727SSebastian Andrzej Siewior 			}
37069364727SSebastian Andrzej Siewior 		}
37169364727SSebastian Andrzej Siewior 		bt_ctf_field_put(field);
37269364727SSebastian Andrzej Siewior 	}
37369364727SSebastian Andrzej Siewior 	if (flags & FIELD_IS_ARRAY) {
37469364727SSebastian Andrzej Siewior 		ret = bt_ctf_event_set_payload(event, name, array_field);
37569364727SSebastian Andrzej Siewior 		if (ret) {
37669364727SSebastian Andrzej Siewior 			pr_err("Failed add payload array %s\n", name);
37769364727SSebastian Andrzej Siewior 			return -1;
37869364727SSebastian Andrzej Siewior 		}
37969364727SSebastian Andrzej Siewior 		bt_ctf_field_put(array_field);
38069364727SSebastian Andrzej Siewior 	}
38169364727SSebastian Andrzej Siewior 	return 0;
38269364727SSebastian Andrzej Siewior 
38369364727SSebastian Andrzej Siewior err_put_field:
38469364727SSebastian Andrzej Siewior 	bt_ctf_field_put(field);
38569364727SSebastian Andrzej Siewior 	return -1;
38669364727SSebastian Andrzej Siewior }
38769364727SSebastian Andrzej Siewior 
38869364727SSebastian Andrzej Siewior static int add_tracepoint_fields_values(struct ctf_writer *cw,
38969364727SSebastian Andrzej Siewior 					struct bt_ctf_event_class *event_class,
39069364727SSebastian Andrzej Siewior 					struct bt_ctf_event *event,
39169364727SSebastian Andrzej Siewior 					struct format_field *fields,
39269364727SSebastian Andrzej Siewior 					struct perf_sample *sample)
39369364727SSebastian Andrzej Siewior {
39469364727SSebastian Andrzej Siewior 	struct format_field *field;
39569364727SSebastian Andrzej Siewior 	int ret;
39669364727SSebastian Andrzej Siewior 
39769364727SSebastian Andrzej Siewior 	for (field = fields; field; field = field->next) {
39869364727SSebastian Andrzej Siewior 		ret = add_tracepoint_field_value(cw, event_class, event, sample,
39969364727SSebastian Andrzej Siewior 				field);
40069364727SSebastian Andrzej Siewior 		if (ret)
40169364727SSebastian Andrzej Siewior 			return -1;
40269364727SSebastian Andrzej Siewior 	}
40369364727SSebastian Andrzej Siewior 	return 0;
40469364727SSebastian Andrzej Siewior }
40569364727SSebastian Andrzej Siewior 
40669364727SSebastian Andrzej Siewior static int add_tracepoint_values(struct ctf_writer *cw,
40769364727SSebastian Andrzej Siewior 				 struct bt_ctf_event_class *event_class,
40869364727SSebastian Andrzej Siewior 				 struct bt_ctf_event *event,
40969364727SSebastian Andrzej Siewior 				 struct perf_evsel *evsel,
41069364727SSebastian Andrzej Siewior 				 struct perf_sample *sample)
41169364727SSebastian Andrzej Siewior {
41269364727SSebastian Andrzej Siewior 	struct format_field *common_fields = evsel->tp_format->format.common_fields;
41369364727SSebastian Andrzej Siewior 	struct format_field *fields        = evsel->tp_format->format.fields;
41469364727SSebastian Andrzej Siewior 	int ret;
41569364727SSebastian Andrzej Siewior 
41669364727SSebastian Andrzej Siewior 	ret = add_tracepoint_fields_values(cw, event_class, event,
41769364727SSebastian Andrzej Siewior 					   common_fields, sample);
41869364727SSebastian Andrzej Siewior 	if (!ret)
41969364727SSebastian Andrzej Siewior 		ret = add_tracepoint_fields_values(cw, event_class, event,
42069364727SSebastian Andrzej Siewior 						   fields, sample);
42169364727SSebastian Andrzej Siewior 
42269364727SSebastian Andrzej Siewior 	return ret;
42369364727SSebastian Andrzej Siewior }
42469364727SSebastian Andrzej Siewior 
4256122d57eSWang Nan static int
4266122d57eSWang Nan add_bpf_output_values(struct bt_ctf_event_class *event_class,
4276122d57eSWang Nan 		      struct bt_ctf_event *event,
4286122d57eSWang Nan 		      struct perf_sample *sample)
4296122d57eSWang Nan {
4306122d57eSWang Nan 	struct bt_ctf_field_type *len_type, *seq_type;
4316122d57eSWang Nan 	struct bt_ctf_field *len_field, *seq_field;
4326122d57eSWang Nan 	unsigned int raw_size = sample->raw_size;
4336122d57eSWang Nan 	unsigned int nr_elements = raw_size / sizeof(u32);
4346122d57eSWang Nan 	unsigned int i;
4356122d57eSWang Nan 	int ret;
4366122d57eSWang Nan 
4376122d57eSWang Nan 	if (nr_elements * sizeof(u32) != raw_size)
4386122d57eSWang Nan 		pr_warning("Incorrect raw_size (%u) in bpf output event, skip %lu bytes\n",
4396122d57eSWang Nan 			   raw_size, nr_elements * sizeof(u32) - raw_size);
4406122d57eSWang Nan 
4416122d57eSWang Nan 	len_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_len");
4426122d57eSWang Nan 	len_field = bt_ctf_field_create(len_type);
4436122d57eSWang Nan 	if (!len_field) {
4446122d57eSWang Nan 		pr_err("failed to create 'raw_len' for bpf output event\n");
4456122d57eSWang Nan 		ret = -1;
4466122d57eSWang Nan 		goto put_len_type;
4476122d57eSWang Nan 	}
4486122d57eSWang Nan 
4496122d57eSWang Nan 	ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements);
4506122d57eSWang Nan 	if (ret) {
4516122d57eSWang Nan 		pr_err("failed to set field value for raw_len\n");
4526122d57eSWang Nan 		goto put_len_field;
4536122d57eSWang Nan 	}
4546122d57eSWang Nan 	ret = bt_ctf_event_set_payload(event, "raw_len", len_field);
4556122d57eSWang Nan 	if (ret) {
4566122d57eSWang Nan 		pr_err("failed to set payload to raw_len\n");
4576122d57eSWang Nan 		goto put_len_field;
4586122d57eSWang Nan 	}
4596122d57eSWang Nan 
4606122d57eSWang Nan 	seq_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_data");
4616122d57eSWang Nan 	seq_field = bt_ctf_field_create(seq_type);
4626122d57eSWang Nan 	if (!seq_field) {
4636122d57eSWang Nan 		pr_err("failed to create 'raw_data' for bpf output event\n");
4646122d57eSWang Nan 		ret = -1;
4656122d57eSWang Nan 		goto put_seq_type;
4666122d57eSWang Nan 	}
4676122d57eSWang Nan 
4686122d57eSWang Nan 	ret = bt_ctf_field_sequence_set_length(seq_field, len_field);
4696122d57eSWang Nan 	if (ret) {
4706122d57eSWang Nan 		pr_err("failed to set length of 'raw_data'\n");
4716122d57eSWang Nan 		goto put_seq_field;
4726122d57eSWang Nan 	}
4736122d57eSWang Nan 
4746122d57eSWang Nan 	for (i = 0; i < nr_elements; i++) {
4756122d57eSWang Nan 		struct bt_ctf_field *elem_field =
4766122d57eSWang Nan 			bt_ctf_field_sequence_get_field(seq_field, i);
4776122d57eSWang Nan 
4786122d57eSWang Nan 		ret = bt_ctf_field_unsigned_integer_set_value(elem_field,
4796122d57eSWang Nan 				((u32 *)(sample->raw_data))[i]);
4806122d57eSWang Nan 
4816122d57eSWang Nan 		bt_ctf_field_put(elem_field);
4826122d57eSWang Nan 		if (ret) {
4836122d57eSWang Nan 			pr_err("failed to set raw_data[%d]\n", i);
4846122d57eSWang Nan 			goto put_seq_field;
4856122d57eSWang Nan 		}
4866122d57eSWang Nan 	}
4876122d57eSWang Nan 
4886122d57eSWang Nan 	ret = bt_ctf_event_set_payload(event, "raw_data", seq_field);
4896122d57eSWang Nan 	if (ret)
4906122d57eSWang Nan 		pr_err("failed to set payload for raw_data\n");
4916122d57eSWang Nan 
4926122d57eSWang Nan put_seq_field:
4936122d57eSWang Nan 	bt_ctf_field_put(seq_field);
4946122d57eSWang Nan put_seq_type:
4956122d57eSWang Nan 	bt_ctf_field_type_put(seq_type);
4966122d57eSWang Nan put_len_field:
4976122d57eSWang Nan 	bt_ctf_field_put(len_field);
4986122d57eSWang Nan put_len_type:
4996122d57eSWang Nan 	bt_ctf_field_type_put(len_type);
5006122d57eSWang Nan 	return ret;
5016122d57eSWang Nan }
5026122d57eSWang Nan 
503edbe9817SJiri Olsa static int add_generic_values(struct ctf_writer *cw,
504edbe9817SJiri Olsa 			      struct bt_ctf_event *event,
505edbe9817SJiri Olsa 			      struct perf_evsel *evsel,
506edbe9817SJiri Olsa 			      struct perf_sample *sample)
507edbe9817SJiri Olsa {
508edbe9817SJiri Olsa 	u64 type = evsel->attr.sample_type;
509edbe9817SJiri Olsa 	int ret;
510edbe9817SJiri Olsa 
511edbe9817SJiri Olsa 	/*
512edbe9817SJiri Olsa 	 * missing:
513edbe9817SJiri Olsa 	 *   PERF_SAMPLE_TIME         - not needed as we have it in
514edbe9817SJiri Olsa 	 *                              ctf event header
515edbe9817SJiri Olsa 	 *   PERF_SAMPLE_READ         - TODO
516edbe9817SJiri Olsa 	 *   PERF_SAMPLE_CALLCHAIN    - TODO
517edbe9817SJiri Olsa 	 *   PERF_SAMPLE_RAW          - tracepoint fields are handled separately
518edbe9817SJiri Olsa 	 *   PERF_SAMPLE_BRANCH_STACK - TODO
519edbe9817SJiri Olsa 	 *   PERF_SAMPLE_REGS_USER    - TODO
520edbe9817SJiri Olsa 	 *   PERF_SAMPLE_STACK_USER   - TODO
521edbe9817SJiri Olsa 	 */
522edbe9817SJiri Olsa 
523edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_IP) {
52454cf776aSSebastian Andrzej Siewior 		ret = value_set_u64_hex(cw, event, "perf_ip", sample->ip);
525edbe9817SJiri Olsa 		if (ret)
526edbe9817SJiri Olsa 			return -1;
527edbe9817SJiri Olsa 	}
528edbe9817SJiri Olsa 
529edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_TID) {
53054cf776aSSebastian Andrzej Siewior 		ret = value_set_s32(cw, event, "perf_tid", sample->tid);
531edbe9817SJiri Olsa 		if (ret)
532edbe9817SJiri Olsa 			return -1;
533edbe9817SJiri Olsa 
53454cf776aSSebastian Andrzej Siewior 		ret = value_set_s32(cw, event, "perf_pid", sample->pid);
535edbe9817SJiri Olsa 		if (ret)
536edbe9817SJiri Olsa 			return -1;
537edbe9817SJiri Olsa 	}
538edbe9817SJiri Olsa 
539edbe9817SJiri Olsa 	if ((type & PERF_SAMPLE_ID) ||
540edbe9817SJiri Olsa 	    (type & PERF_SAMPLE_IDENTIFIER)) {
54154cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_id", sample->id);
542edbe9817SJiri Olsa 		if (ret)
543edbe9817SJiri Olsa 			return -1;
544edbe9817SJiri Olsa 	}
545edbe9817SJiri Olsa 
546edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_STREAM_ID) {
54754cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_stream_id", sample->stream_id);
548edbe9817SJiri Olsa 		if (ret)
549edbe9817SJiri Olsa 			return -1;
550edbe9817SJiri Olsa 	}
551edbe9817SJiri Olsa 
552edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_PERIOD) {
55354cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_period", sample->period);
554edbe9817SJiri Olsa 		if (ret)
555edbe9817SJiri Olsa 			return -1;
556edbe9817SJiri Olsa 	}
557edbe9817SJiri Olsa 
558edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_WEIGHT) {
55954cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_weight", sample->weight);
560edbe9817SJiri Olsa 		if (ret)
561edbe9817SJiri Olsa 			return -1;
562edbe9817SJiri Olsa 	}
563edbe9817SJiri Olsa 
564edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_DATA_SRC) {
56554cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_data_src",
56654cf776aSSebastian Andrzej Siewior 				sample->data_src);
567edbe9817SJiri Olsa 		if (ret)
568edbe9817SJiri Olsa 			return -1;
569edbe9817SJiri Olsa 	}
570edbe9817SJiri Olsa 
571edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_TRANSACTION) {
57254cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_transaction",
57354cf776aSSebastian Andrzej Siewior 				sample->transaction);
574edbe9817SJiri Olsa 		if (ret)
575edbe9817SJiri Olsa 			return -1;
576edbe9817SJiri Olsa 	}
577edbe9817SJiri Olsa 
578edbe9817SJiri Olsa 	return 0;
579edbe9817SJiri Olsa }
580edbe9817SJiri Olsa 
58190e129ffSSebastian Andrzej Siewior static int ctf_stream__flush(struct ctf_stream *cs)
58290e129ffSSebastian Andrzej Siewior {
58390e129ffSSebastian Andrzej Siewior 	int err = 0;
58490e129ffSSebastian Andrzej Siewior 
58590e129ffSSebastian Andrzej Siewior 	if (cs) {
58690e129ffSSebastian Andrzej Siewior 		err = bt_ctf_stream_flush(cs->stream);
58790e129ffSSebastian Andrzej Siewior 		if (err)
58890e129ffSSebastian Andrzej Siewior 			pr_err("CTF stream %d flush failed\n", cs->cpu);
58990e129ffSSebastian Andrzej Siewior 
59089e5fa88SJiri Olsa 		pr("Flush stream for cpu %d (%u samples)\n",
59189e5fa88SJiri Olsa 		   cs->cpu, cs->count);
59289e5fa88SJiri Olsa 
59389e5fa88SJiri Olsa 		cs->count = 0;
59490e129ffSSebastian Andrzej Siewior 	}
59590e129ffSSebastian Andrzej Siewior 
59690e129ffSSebastian Andrzej Siewior 	return err;
59790e129ffSSebastian Andrzej Siewior }
59890e129ffSSebastian Andrzej Siewior 
59990e129ffSSebastian Andrzej Siewior static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu)
60090e129ffSSebastian Andrzej Siewior {
60190e129ffSSebastian Andrzej Siewior 	struct ctf_stream *cs;
60290e129ffSSebastian Andrzej Siewior 	struct bt_ctf_field *pkt_ctx   = NULL;
60390e129ffSSebastian Andrzej Siewior 	struct bt_ctf_field *cpu_field = NULL;
60490e129ffSSebastian Andrzej Siewior 	struct bt_ctf_stream *stream   = NULL;
60590e129ffSSebastian Andrzej Siewior 	int ret;
60690e129ffSSebastian Andrzej Siewior 
60790e129ffSSebastian Andrzej Siewior 	cs = zalloc(sizeof(*cs));
60890e129ffSSebastian Andrzej Siewior 	if (!cs) {
60990e129ffSSebastian Andrzej Siewior 		pr_err("Failed to allocate ctf stream\n");
61090e129ffSSebastian Andrzej Siewior 		return NULL;
61190e129ffSSebastian Andrzej Siewior 	}
61290e129ffSSebastian Andrzej Siewior 
61390e129ffSSebastian Andrzej Siewior 	stream = bt_ctf_writer_create_stream(cw->writer, cw->stream_class);
61490e129ffSSebastian Andrzej Siewior 	if (!stream) {
61590e129ffSSebastian Andrzej Siewior 		pr_err("Failed to create CTF stream\n");
61690e129ffSSebastian Andrzej Siewior 		goto out;
61790e129ffSSebastian Andrzej Siewior 	}
61890e129ffSSebastian Andrzej Siewior 
61990e129ffSSebastian Andrzej Siewior 	pkt_ctx = bt_ctf_stream_get_packet_context(stream);
62090e129ffSSebastian Andrzej Siewior 	if (!pkt_ctx) {
62190e129ffSSebastian Andrzej Siewior 		pr_err("Failed to obtain packet context\n");
62290e129ffSSebastian Andrzej Siewior 		goto out;
62390e129ffSSebastian Andrzej Siewior 	}
62490e129ffSSebastian Andrzej Siewior 
62590e129ffSSebastian Andrzej Siewior 	cpu_field = bt_ctf_field_structure_get_field(pkt_ctx, "cpu_id");
62690e129ffSSebastian Andrzej Siewior 	bt_ctf_field_put(pkt_ctx);
62790e129ffSSebastian Andrzej Siewior 	if (!cpu_field) {
62890e129ffSSebastian Andrzej Siewior 		pr_err("Failed to obtain cpu field\n");
62990e129ffSSebastian Andrzej Siewior 		goto out;
63090e129ffSSebastian Andrzej Siewior 	}
63190e129ffSSebastian Andrzej Siewior 
63290e129ffSSebastian Andrzej Siewior 	ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu);
63390e129ffSSebastian Andrzej Siewior 	if (ret) {
63490e129ffSSebastian Andrzej Siewior 		pr_err("Failed to update CPU number\n");
63590e129ffSSebastian Andrzej Siewior 		goto out;
63690e129ffSSebastian Andrzej Siewior 	}
63790e129ffSSebastian Andrzej Siewior 
63890e129ffSSebastian Andrzej Siewior 	bt_ctf_field_put(cpu_field);
63990e129ffSSebastian Andrzej Siewior 
64090e129ffSSebastian Andrzej Siewior 	cs->cpu    = cpu;
64190e129ffSSebastian Andrzej Siewior 	cs->stream = stream;
64290e129ffSSebastian Andrzej Siewior 	return cs;
64390e129ffSSebastian Andrzej Siewior 
64490e129ffSSebastian Andrzej Siewior out:
64590e129ffSSebastian Andrzej Siewior 	if (cpu_field)
64690e129ffSSebastian Andrzej Siewior 		bt_ctf_field_put(cpu_field);
64790e129ffSSebastian Andrzej Siewior 	if (stream)
64890e129ffSSebastian Andrzej Siewior 		bt_ctf_stream_put(stream);
64990e129ffSSebastian Andrzej Siewior 
65090e129ffSSebastian Andrzej Siewior 	free(cs);
65190e129ffSSebastian Andrzej Siewior 	return NULL;
65290e129ffSSebastian Andrzej Siewior }
65390e129ffSSebastian Andrzej Siewior 
65490e129ffSSebastian Andrzej Siewior static void ctf_stream__delete(struct ctf_stream *cs)
65590e129ffSSebastian Andrzej Siewior {
65690e129ffSSebastian Andrzej Siewior 	if (cs) {
65790e129ffSSebastian Andrzej Siewior 		bt_ctf_stream_put(cs->stream);
65890e129ffSSebastian Andrzej Siewior 		free(cs);
65990e129ffSSebastian Andrzej Siewior 	}
66090e129ffSSebastian Andrzej Siewior }
66190e129ffSSebastian Andrzej Siewior 
66290e129ffSSebastian Andrzej Siewior static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu)
66390e129ffSSebastian Andrzej Siewior {
66490e129ffSSebastian Andrzej Siewior 	struct ctf_stream *cs = cw->stream[cpu];
66590e129ffSSebastian Andrzej Siewior 
66690e129ffSSebastian Andrzej Siewior 	if (!cs) {
66790e129ffSSebastian Andrzej Siewior 		cs = ctf_stream__create(cw, cpu);
66890e129ffSSebastian Andrzej Siewior 		cw->stream[cpu] = cs;
66990e129ffSSebastian Andrzej Siewior 	}
67090e129ffSSebastian Andrzej Siewior 
67190e129ffSSebastian Andrzej Siewior 	return cs;
67290e129ffSSebastian Andrzej Siewior }
67390e129ffSSebastian Andrzej Siewior 
67490e129ffSSebastian Andrzej Siewior static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample,
67590e129ffSSebastian Andrzej Siewior 			  struct perf_evsel *evsel)
67690e129ffSSebastian Andrzej Siewior {
67790e129ffSSebastian Andrzej Siewior 	int cpu = 0;
67890e129ffSSebastian Andrzej Siewior 
67990e129ffSSebastian Andrzej Siewior 	if (evsel->attr.sample_type & PERF_SAMPLE_CPU)
68090e129ffSSebastian Andrzej Siewior 		cpu = sample->cpu;
68190e129ffSSebastian Andrzej Siewior 
68290e129ffSSebastian Andrzej Siewior 	if (cpu > cw->stream_cnt) {
68390e129ffSSebastian Andrzej Siewior 		pr_err("Event was recorded for CPU %d, limit is at %d.\n",
68490e129ffSSebastian Andrzej Siewior 			cpu, cw->stream_cnt);
68590e129ffSSebastian Andrzej Siewior 		cpu = 0;
68690e129ffSSebastian Andrzej Siewior 	}
68790e129ffSSebastian Andrzej Siewior 
68890e129ffSSebastian Andrzej Siewior 	return cpu;
68990e129ffSSebastian Andrzej Siewior }
69090e129ffSSebastian Andrzej Siewior 
69189e5fa88SJiri Olsa #define STREAM_FLUSH_COUNT 100000
69289e5fa88SJiri Olsa 
69389e5fa88SJiri Olsa /*
69489e5fa88SJiri Olsa  * Currently we have no other way to determine the
69589e5fa88SJiri Olsa  * time for the stream flush other than keep track
69689e5fa88SJiri Olsa  * of the number of events and check it against
69789e5fa88SJiri Olsa  * threshold.
69889e5fa88SJiri Olsa  */
69989e5fa88SJiri Olsa static bool is_flush_needed(struct ctf_stream *cs)
70089e5fa88SJiri Olsa {
70189e5fa88SJiri Olsa 	return cs->count >= STREAM_FLUSH_COUNT;
70289e5fa88SJiri Olsa }
70389e5fa88SJiri Olsa 
704edbe9817SJiri Olsa static int process_sample_event(struct perf_tool *tool,
705b8f8eb84SArnaldo Carvalho de Melo 				union perf_event *_event,
706edbe9817SJiri Olsa 				struct perf_sample *sample,
707edbe9817SJiri Olsa 				struct perf_evsel *evsel,
708edbe9817SJiri Olsa 				struct machine *machine __maybe_unused)
709edbe9817SJiri Olsa {
710edbe9817SJiri Olsa 	struct convert *c = container_of(tool, struct convert, tool);
711edbe9817SJiri Olsa 	struct evsel_priv *priv = evsel->priv;
712edbe9817SJiri Olsa 	struct ctf_writer *cw = &c->writer;
71390e129ffSSebastian Andrzej Siewior 	struct ctf_stream *cs;
714edbe9817SJiri Olsa 	struct bt_ctf_event_class *event_class;
715edbe9817SJiri Olsa 	struct bt_ctf_event *event;
716edbe9817SJiri Olsa 	int ret;
717edbe9817SJiri Olsa 
718edbe9817SJiri Olsa 	if (WARN_ONCE(!priv, "Failed to setup all events.\n"))
719edbe9817SJiri Olsa 		return 0;
720edbe9817SJiri Olsa 
721edbe9817SJiri Olsa 	event_class = priv->event_class;
722edbe9817SJiri Olsa 
723edbe9817SJiri Olsa 	/* update stats */
724edbe9817SJiri Olsa 	c->events_count++;
725edbe9817SJiri Olsa 	c->events_size += _event->header.size;
726edbe9817SJiri Olsa 
727edbe9817SJiri Olsa 	pr_time2(sample->time, "sample %" PRIu64 "\n", c->events_count);
728edbe9817SJiri Olsa 
729edbe9817SJiri Olsa 	event = bt_ctf_event_create(event_class);
730edbe9817SJiri Olsa 	if (!event) {
731edbe9817SJiri Olsa 		pr_err("Failed to create an CTF event\n");
732edbe9817SJiri Olsa 		return -1;
733edbe9817SJiri Olsa 	}
734edbe9817SJiri Olsa 
735edbe9817SJiri Olsa 	bt_ctf_clock_set_time(cw->clock, sample->time);
736edbe9817SJiri Olsa 
737edbe9817SJiri Olsa 	ret = add_generic_values(cw, event, evsel, sample);
738edbe9817SJiri Olsa 	if (ret)
739edbe9817SJiri Olsa 		return -1;
740edbe9817SJiri Olsa 
74169364727SSebastian Andrzej Siewior 	if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
74269364727SSebastian Andrzej Siewior 		ret = add_tracepoint_values(cw, event_class, event,
74369364727SSebastian Andrzej Siewior 					    evsel, sample);
74469364727SSebastian Andrzej Siewior 		if (ret)
74569364727SSebastian Andrzej Siewior 			return -1;
74669364727SSebastian Andrzej Siewior 	}
74769364727SSebastian Andrzej Siewior 
7486122d57eSWang Nan 	if (perf_evsel__is_bpf_output(evsel)) {
7496122d57eSWang Nan 		ret = add_bpf_output_values(event_class, event, sample);
7506122d57eSWang Nan 		if (ret)
7516122d57eSWang Nan 			return -1;
7526122d57eSWang Nan 	}
7536122d57eSWang Nan 
75490e129ffSSebastian Andrzej Siewior 	cs = ctf_stream(cw, get_sample_cpu(cw, sample, evsel));
75589e5fa88SJiri Olsa 	if (cs) {
75689e5fa88SJiri Olsa 		if (is_flush_needed(cs))
75789e5fa88SJiri Olsa 			ctf_stream__flush(cs);
75889e5fa88SJiri Olsa 
75989e5fa88SJiri Olsa 		cs->count++;
76090e129ffSSebastian Andrzej Siewior 		bt_ctf_stream_append_event(cs->stream, event);
76189e5fa88SJiri Olsa 	}
76290e129ffSSebastian Andrzej Siewior 
763edbe9817SJiri Olsa 	bt_ctf_event_put(event);
76490e129ffSSebastian Andrzej Siewior 	return cs ? 0 : -1;
765edbe9817SJiri Olsa }
766edbe9817SJiri Olsa 
767*f5a08cedSWang Nan #define __NON_SAMPLE_SET_FIELD(_name, _type, _field) 	\
768*f5a08cedSWang Nan do {							\
769*f5a08cedSWang Nan 	ret = value_set_##_type(cw, event, #_field, _event->_name._field);\
770*f5a08cedSWang Nan 	if (ret)					\
771*f5a08cedSWang Nan 		return -1;				\
772*f5a08cedSWang Nan } while(0)
773*f5a08cedSWang Nan 
774*f5a08cedSWang Nan #define __FUNC_PROCESS_NON_SAMPLE(_name, body) 	\
775*f5a08cedSWang Nan static int process_##_name##_event(struct perf_tool *tool,	\
776*f5a08cedSWang Nan 				   union perf_event *_event,	\
777*f5a08cedSWang Nan 				   struct perf_sample *sample,	\
778*f5a08cedSWang Nan 				   struct machine *machine)	\
779*f5a08cedSWang Nan {								\
780*f5a08cedSWang Nan 	struct convert *c = container_of(tool, struct convert, tool);\
781*f5a08cedSWang Nan 	struct ctf_writer *cw = &c->writer;			\
782*f5a08cedSWang Nan 	struct bt_ctf_event_class *event_class = cw->_name##_class;\
783*f5a08cedSWang Nan 	struct bt_ctf_event *event;				\
784*f5a08cedSWang Nan 	struct ctf_stream *cs;					\
785*f5a08cedSWang Nan 	int ret;						\
786*f5a08cedSWang Nan 								\
787*f5a08cedSWang Nan 	c->non_sample_count++;					\
788*f5a08cedSWang Nan 	c->events_size += _event->header.size;			\
789*f5a08cedSWang Nan 	event = bt_ctf_event_create(event_class);		\
790*f5a08cedSWang Nan 	if (!event) {						\
791*f5a08cedSWang Nan 		pr_err("Failed to create an CTF event\n");	\
792*f5a08cedSWang Nan 		return -1;					\
793*f5a08cedSWang Nan 	}							\
794*f5a08cedSWang Nan 								\
795*f5a08cedSWang Nan 	bt_ctf_clock_set_time(cw->clock, sample->time);		\
796*f5a08cedSWang Nan 	body							\
797*f5a08cedSWang Nan 	cs = ctf_stream(cw, 0);					\
798*f5a08cedSWang Nan 	if (cs) {						\
799*f5a08cedSWang Nan 		if (is_flush_needed(cs))			\
800*f5a08cedSWang Nan 			ctf_stream__flush(cs);			\
801*f5a08cedSWang Nan 								\
802*f5a08cedSWang Nan 		cs->count++;					\
803*f5a08cedSWang Nan 		bt_ctf_stream_append_event(cs->stream, event);	\
804*f5a08cedSWang Nan 	}							\
805*f5a08cedSWang Nan 	bt_ctf_event_put(event);				\
806*f5a08cedSWang Nan 								\
807*f5a08cedSWang Nan 	return perf_event__process_##_name(tool, _event, sample, machine);\
808*f5a08cedSWang Nan }
809*f5a08cedSWang Nan 
810*f5a08cedSWang Nan __FUNC_PROCESS_NON_SAMPLE(comm,
811*f5a08cedSWang Nan 	__NON_SAMPLE_SET_FIELD(comm, u32, pid);
812*f5a08cedSWang Nan 	__NON_SAMPLE_SET_FIELD(comm, u32, tid);
813*f5a08cedSWang Nan 	__NON_SAMPLE_SET_FIELD(comm, string, comm);
814*f5a08cedSWang Nan )
815*f5a08cedSWang Nan #undef __NON_SAMPLE_SET_FIELD
816*f5a08cedSWang Nan #undef __FUNC_PROCESS_NON_SAMPLE
817*f5a08cedSWang Nan 
818e0a7cce5SWang Nan /* If dup < 0, add a prefix. Else, add _dupl_X suffix. */
819e0a7cce5SWang Nan static char *change_name(char *name, char *orig_name, int dup)
820e0a7cce5SWang Nan {
821e0a7cce5SWang Nan 	char *new_name = NULL;
822e0a7cce5SWang Nan 	size_t len;
823e0a7cce5SWang Nan 
824e0a7cce5SWang Nan 	if (!name)
825e0a7cce5SWang Nan 		name = orig_name;
826e0a7cce5SWang Nan 
827e0a7cce5SWang Nan 	if (dup >= 10)
828e0a7cce5SWang Nan 		goto out;
829e0a7cce5SWang Nan 	/*
830e0a7cce5SWang Nan 	 * Add '_' prefix to potential keywork.  According to
831e0a7cce5SWang Nan 	 * Mathieu Desnoyers (https://lkml.org/lkml/2015/1/23/652),
832e0a7cce5SWang Nan 	 * futher CTF spec updating may require us to use '$'.
833e0a7cce5SWang Nan 	 */
834e0a7cce5SWang Nan 	if (dup < 0)
835e0a7cce5SWang Nan 		len = strlen(name) + sizeof("_");
836e0a7cce5SWang Nan 	else
837e0a7cce5SWang Nan 		len = strlen(orig_name) + sizeof("_dupl_X");
838e0a7cce5SWang Nan 
839e0a7cce5SWang Nan 	new_name = malloc(len);
840e0a7cce5SWang Nan 	if (!new_name)
841e0a7cce5SWang Nan 		goto out;
842e0a7cce5SWang Nan 
843e0a7cce5SWang Nan 	if (dup < 0)
844e0a7cce5SWang Nan 		snprintf(new_name, len, "_%s", name);
845e0a7cce5SWang Nan 	else
846e0a7cce5SWang Nan 		snprintf(new_name, len, "%s_dupl_%d", orig_name, dup);
847e0a7cce5SWang Nan 
848e0a7cce5SWang Nan out:
849e0a7cce5SWang Nan 	if (name != orig_name)
850e0a7cce5SWang Nan 		free(name);
851e0a7cce5SWang Nan 	return new_name;
852e0a7cce5SWang Nan }
853e0a7cce5SWang Nan 
854e0a7cce5SWang Nan static int event_class_add_field(struct bt_ctf_event_class *event_class,
855e0a7cce5SWang Nan 		struct bt_ctf_field_type *type,
856e0a7cce5SWang Nan 		struct format_field *field)
857e0a7cce5SWang Nan {
858e0a7cce5SWang Nan 	struct bt_ctf_field_type *t = NULL;
859e0a7cce5SWang Nan 	char *name;
860e0a7cce5SWang Nan 	int dup = 1;
861e0a7cce5SWang Nan 	int ret;
862e0a7cce5SWang Nan 
863e0a7cce5SWang Nan 	/* alias was already assigned */
864e0a7cce5SWang Nan 	if (field->alias != field->name)
865e0a7cce5SWang Nan 		return bt_ctf_event_class_add_field(event_class, type,
866e0a7cce5SWang Nan 				(char *)field->alias);
867e0a7cce5SWang Nan 
868e0a7cce5SWang Nan 	name = field->name;
869e0a7cce5SWang Nan 
870e0a7cce5SWang Nan 	/* If 'name' is a keywork, add prefix. */
871e0a7cce5SWang Nan 	if (bt_ctf_validate_identifier(name))
872e0a7cce5SWang Nan 		name = change_name(name, field->name, -1);
873e0a7cce5SWang Nan 
874e0a7cce5SWang Nan 	if (!name) {
875e0a7cce5SWang Nan 		pr_err("Failed to fix invalid identifier.");
876e0a7cce5SWang Nan 		return -1;
877e0a7cce5SWang Nan 	}
878e0a7cce5SWang Nan 	while ((t = bt_ctf_event_class_get_field_by_name(event_class, name))) {
879e0a7cce5SWang Nan 		bt_ctf_field_type_put(t);
880e0a7cce5SWang Nan 		name = change_name(name, field->name, dup++);
881e0a7cce5SWang Nan 		if (!name) {
882e0a7cce5SWang Nan 			pr_err("Failed to create dup name for '%s'\n", field->name);
883e0a7cce5SWang Nan 			return -1;
884e0a7cce5SWang Nan 		}
885e0a7cce5SWang Nan 	}
886e0a7cce5SWang Nan 
887e0a7cce5SWang Nan 	ret = bt_ctf_event_class_add_field(event_class, type, name);
888e0a7cce5SWang Nan 	if (!ret)
889e0a7cce5SWang Nan 		field->alias = name;
890e0a7cce5SWang Nan 
891e0a7cce5SWang Nan 	return ret;
892e0a7cce5SWang Nan }
893e0a7cce5SWang Nan 
89469364727SSebastian Andrzej Siewior static int add_tracepoint_fields_types(struct ctf_writer *cw,
89569364727SSebastian Andrzej Siewior 				       struct format_field *fields,
89669364727SSebastian Andrzej Siewior 				       struct bt_ctf_event_class *event_class)
89769364727SSebastian Andrzej Siewior {
89869364727SSebastian Andrzej Siewior 	struct format_field *field;
89969364727SSebastian Andrzej Siewior 	int ret;
90069364727SSebastian Andrzej Siewior 
90169364727SSebastian Andrzej Siewior 	for (field = fields; field; field = field->next) {
90269364727SSebastian Andrzej Siewior 		struct bt_ctf_field_type *type;
90369364727SSebastian Andrzej Siewior 		unsigned long flags = field->flags;
90469364727SSebastian Andrzej Siewior 
90569364727SSebastian Andrzej Siewior 		pr2("  field '%s'\n", field->name);
90669364727SSebastian Andrzej Siewior 
90769364727SSebastian Andrzej Siewior 		type = get_tracepoint_field_type(cw, field);
90869364727SSebastian Andrzej Siewior 		if (!type)
90969364727SSebastian Andrzej Siewior 			return -1;
91069364727SSebastian Andrzej Siewior 
91169364727SSebastian Andrzej Siewior 		/*
91269364727SSebastian Andrzej Siewior 		 * A string is an array of chars. For this we use the string
91369364727SSebastian Andrzej Siewior 		 * type and don't care that it is an array. What we don't
91469364727SSebastian Andrzej Siewior 		 * support is an array of strings.
91569364727SSebastian Andrzej Siewior 		 */
91669364727SSebastian Andrzej Siewior 		if (flags & FIELD_IS_STRING)
91769364727SSebastian Andrzej Siewior 			flags &= ~FIELD_IS_ARRAY;
91869364727SSebastian Andrzej Siewior 
91969364727SSebastian Andrzej Siewior 		if (flags & FIELD_IS_ARRAY)
92069364727SSebastian Andrzej Siewior 			type = bt_ctf_field_type_array_create(type, field->arraylen);
92169364727SSebastian Andrzej Siewior 
922e0a7cce5SWang Nan 		ret = event_class_add_field(event_class, type, field);
92369364727SSebastian Andrzej Siewior 
92469364727SSebastian Andrzej Siewior 		if (flags & FIELD_IS_ARRAY)
92569364727SSebastian Andrzej Siewior 			bt_ctf_field_type_put(type);
92669364727SSebastian Andrzej Siewior 
92769364727SSebastian Andrzej Siewior 		if (ret) {
928e0a7cce5SWang Nan 			pr_err("Failed to add field '%s': %d\n",
929e0a7cce5SWang Nan 					field->name, ret);
93069364727SSebastian Andrzej Siewior 			return -1;
93169364727SSebastian Andrzej Siewior 		}
93269364727SSebastian Andrzej Siewior 	}
93369364727SSebastian Andrzej Siewior 
93469364727SSebastian Andrzej Siewior 	return 0;
93569364727SSebastian Andrzej Siewior }
93669364727SSebastian Andrzej Siewior 
93769364727SSebastian Andrzej Siewior static int add_tracepoint_types(struct ctf_writer *cw,
93869364727SSebastian Andrzej Siewior 				struct perf_evsel *evsel,
93969364727SSebastian Andrzej Siewior 				struct bt_ctf_event_class *class)
94069364727SSebastian Andrzej Siewior {
94169364727SSebastian Andrzej Siewior 	struct format_field *common_fields = evsel->tp_format->format.common_fields;
94269364727SSebastian Andrzej Siewior 	struct format_field *fields        = evsel->tp_format->format.fields;
94369364727SSebastian Andrzej Siewior 	int ret;
94469364727SSebastian Andrzej Siewior 
94569364727SSebastian Andrzej Siewior 	ret = add_tracepoint_fields_types(cw, common_fields, class);
94669364727SSebastian Andrzej Siewior 	if (!ret)
94769364727SSebastian Andrzej Siewior 		ret = add_tracepoint_fields_types(cw, fields, class);
94869364727SSebastian Andrzej Siewior 
94969364727SSebastian Andrzej Siewior 	return ret;
95069364727SSebastian Andrzej Siewior }
95169364727SSebastian Andrzej Siewior 
9526122d57eSWang Nan static int add_bpf_output_types(struct ctf_writer *cw,
9536122d57eSWang Nan 				struct bt_ctf_event_class *class)
9546122d57eSWang Nan {
9556122d57eSWang Nan 	struct bt_ctf_field_type *len_type = cw->data.u32;
9566122d57eSWang Nan 	struct bt_ctf_field_type *seq_base_type = cw->data.u32_hex;
9576122d57eSWang Nan 	struct bt_ctf_field_type *seq_type;
9586122d57eSWang Nan 	int ret;
9596122d57eSWang Nan 
9606122d57eSWang Nan 	ret = bt_ctf_event_class_add_field(class, len_type, "raw_len");
9616122d57eSWang Nan 	if (ret)
9626122d57eSWang Nan 		return ret;
9636122d57eSWang Nan 
9646122d57eSWang Nan 	seq_type = bt_ctf_field_type_sequence_create(seq_base_type, "raw_len");
9656122d57eSWang Nan 	if (!seq_type)
9666122d57eSWang Nan 		return -1;
9676122d57eSWang Nan 
9686122d57eSWang Nan 	return bt_ctf_event_class_add_field(class, seq_type, "raw_data");
9696122d57eSWang Nan }
9706122d57eSWang Nan 
971edbe9817SJiri Olsa static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
972edbe9817SJiri Olsa 			     struct bt_ctf_event_class *event_class)
973edbe9817SJiri Olsa {
974edbe9817SJiri Olsa 	u64 type = evsel->attr.sample_type;
975edbe9817SJiri Olsa 
976edbe9817SJiri Olsa 	/*
977edbe9817SJiri Olsa 	 * missing:
978edbe9817SJiri Olsa 	 *   PERF_SAMPLE_TIME         - not needed as we have it in
979edbe9817SJiri Olsa 	 *                              ctf event header
980edbe9817SJiri Olsa 	 *   PERF_SAMPLE_READ         - TODO
981edbe9817SJiri Olsa 	 *   PERF_SAMPLE_CALLCHAIN    - TODO
9826122d57eSWang Nan 	 *   PERF_SAMPLE_RAW          - tracepoint fields and BPF output
9836122d57eSWang Nan 	 *                              are handled separately
984edbe9817SJiri Olsa 	 *   PERF_SAMPLE_BRANCH_STACK - TODO
985edbe9817SJiri Olsa 	 *   PERF_SAMPLE_REGS_USER    - TODO
986edbe9817SJiri Olsa 	 *   PERF_SAMPLE_STACK_USER   - TODO
987edbe9817SJiri Olsa 	 */
988edbe9817SJiri Olsa 
989edbe9817SJiri Olsa #define ADD_FIELD(cl, t, n)						\
990edbe9817SJiri Olsa 	do {								\
991edbe9817SJiri Olsa 		pr2("  field '%s'\n", n);				\
992edbe9817SJiri Olsa 		if (bt_ctf_event_class_add_field(cl, t, n)) {		\
993e0a7cce5SWang Nan 			pr_err("Failed to add field '%s';\n", n);	\
994edbe9817SJiri Olsa 			return -1;					\
995edbe9817SJiri Olsa 		}							\
996edbe9817SJiri Olsa 	} while (0)
997edbe9817SJiri Olsa 
998edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_IP)
99954cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64_hex, "perf_ip");
1000edbe9817SJiri Olsa 
1001edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_TID) {
100254cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.s32, "perf_tid");
100354cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.s32, "perf_pid");
1004edbe9817SJiri Olsa 	}
1005edbe9817SJiri Olsa 
1006edbe9817SJiri Olsa 	if ((type & PERF_SAMPLE_ID) ||
1007edbe9817SJiri Olsa 	    (type & PERF_SAMPLE_IDENTIFIER))
100854cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_id");
1009edbe9817SJiri Olsa 
1010edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_STREAM_ID)
101154cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_stream_id");
1012edbe9817SJiri Olsa 
1013edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_PERIOD)
101454cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_period");
1015edbe9817SJiri Olsa 
1016edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_WEIGHT)
101754cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_weight");
1018edbe9817SJiri Olsa 
1019edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_DATA_SRC)
102054cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_data_src");
1021edbe9817SJiri Olsa 
1022edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_TRANSACTION)
102354cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_transaction");
1024edbe9817SJiri Olsa 
1025edbe9817SJiri Olsa #undef ADD_FIELD
1026edbe9817SJiri Olsa 	return 0;
1027edbe9817SJiri Olsa }
1028edbe9817SJiri Olsa 
1029edbe9817SJiri Olsa static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
1030edbe9817SJiri Olsa {
1031edbe9817SJiri Olsa 	struct bt_ctf_event_class *event_class;
1032edbe9817SJiri Olsa 	struct evsel_priv *priv;
1033edbe9817SJiri Olsa 	const char *name = perf_evsel__name(evsel);
1034edbe9817SJiri Olsa 	int ret;
1035edbe9817SJiri Olsa 
1036edbe9817SJiri Olsa 	pr("Adding event '%s' (type %d)\n", name, evsel->attr.type);
1037edbe9817SJiri Olsa 
1038edbe9817SJiri Olsa 	event_class = bt_ctf_event_class_create(name);
1039edbe9817SJiri Olsa 	if (!event_class)
1040edbe9817SJiri Olsa 		return -1;
1041edbe9817SJiri Olsa 
1042edbe9817SJiri Olsa 	ret = add_generic_types(cw, evsel, event_class);
1043edbe9817SJiri Olsa 	if (ret)
1044edbe9817SJiri Olsa 		goto err;
1045edbe9817SJiri Olsa 
104669364727SSebastian Andrzej Siewior 	if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
104769364727SSebastian Andrzej Siewior 		ret = add_tracepoint_types(cw, evsel, event_class);
104869364727SSebastian Andrzej Siewior 		if (ret)
104969364727SSebastian Andrzej Siewior 			goto err;
105069364727SSebastian Andrzej Siewior 	}
105169364727SSebastian Andrzej Siewior 
10526122d57eSWang Nan 	if (perf_evsel__is_bpf_output(evsel)) {
10536122d57eSWang Nan 		ret = add_bpf_output_types(cw, event_class);
10546122d57eSWang Nan 		if (ret)
10556122d57eSWang Nan 			goto err;
10566122d57eSWang Nan 	}
10576122d57eSWang Nan 
1058edbe9817SJiri Olsa 	ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);
1059edbe9817SJiri Olsa 	if (ret) {
1060edbe9817SJiri Olsa 		pr("Failed to add event class into stream.\n");
1061edbe9817SJiri Olsa 		goto err;
1062edbe9817SJiri Olsa 	}
1063edbe9817SJiri Olsa 
1064edbe9817SJiri Olsa 	priv = malloc(sizeof(*priv));
1065edbe9817SJiri Olsa 	if (!priv)
1066edbe9817SJiri Olsa 		goto err;
1067edbe9817SJiri Olsa 
1068edbe9817SJiri Olsa 	priv->event_class = event_class;
1069edbe9817SJiri Olsa 	evsel->priv       = priv;
1070edbe9817SJiri Olsa 	return 0;
1071edbe9817SJiri Olsa 
1072edbe9817SJiri Olsa err:
1073edbe9817SJiri Olsa 	bt_ctf_event_class_put(event_class);
1074edbe9817SJiri Olsa 	pr_err("Failed to add event '%s'.\n", name);
1075edbe9817SJiri Olsa 	return -1;
1076edbe9817SJiri Olsa }
1077edbe9817SJiri Olsa 
1078edbe9817SJiri Olsa static int setup_events(struct ctf_writer *cw, struct perf_session *session)
1079edbe9817SJiri Olsa {
1080edbe9817SJiri Olsa 	struct perf_evlist *evlist = session->evlist;
1081edbe9817SJiri Olsa 	struct perf_evsel *evsel;
1082edbe9817SJiri Olsa 	int ret;
1083edbe9817SJiri Olsa 
1084e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
1085edbe9817SJiri Olsa 		ret = add_event(cw, evsel);
1086edbe9817SJiri Olsa 		if (ret)
1087edbe9817SJiri Olsa 			return ret;
1088edbe9817SJiri Olsa 	}
1089edbe9817SJiri Olsa 	return 0;
1090edbe9817SJiri Olsa }
1091edbe9817SJiri Olsa 
1092*f5a08cedSWang Nan #define __NON_SAMPLE_ADD_FIELD(t, n)						\
1093*f5a08cedSWang Nan 	do {							\
1094*f5a08cedSWang Nan 		pr2("  field '%s'\n", #n);			\
1095*f5a08cedSWang Nan 		if (bt_ctf_event_class_add_field(event_class, cw->data.t, #n)) {\
1096*f5a08cedSWang Nan 			pr_err("Failed to add field '%s';\n", #n);\
1097*f5a08cedSWang Nan 			return -1;				\
1098*f5a08cedSWang Nan 		}						\
1099*f5a08cedSWang Nan 	} while(0)
1100*f5a08cedSWang Nan 
1101*f5a08cedSWang Nan #define __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(_name, body) 		\
1102*f5a08cedSWang Nan static int add_##_name##_event(struct ctf_writer *cw)		\
1103*f5a08cedSWang Nan {								\
1104*f5a08cedSWang Nan 	struct bt_ctf_event_class *event_class;			\
1105*f5a08cedSWang Nan 	int ret;						\
1106*f5a08cedSWang Nan 								\
1107*f5a08cedSWang Nan 	pr("Adding "#_name" event\n");				\
1108*f5a08cedSWang Nan 	event_class = bt_ctf_event_class_create("perf_" #_name);\
1109*f5a08cedSWang Nan 	if (!event_class)					\
1110*f5a08cedSWang Nan 		return -1;					\
1111*f5a08cedSWang Nan 	body							\
1112*f5a08cedSWang Nan 								\
1113*f5a08cedSWang Nan 	ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);\
1114*f5a08cedSWang Nan 	if (ret) {						\
1115*f5a08cedSWang Nan 		pr("Failed to add event class '"#_name"' into stream.\n");\
1116*f5a08cedSWang Nan 		return ret;					\
1117*f5a08cedSWang Nan 	}							\
1118*f5a08cedSWang Nan 								\
1119*f5a08cedSWang Nan 	cw->_name##_class = event_class;			\
1120*f5a08cedSWang Nan 	bt_ctf_event_class_put(event_class);			\
1121*f5a08cedSWang Nan 	return 0;						\
1122*f5a08cedSWang Nan }
1123*f5a08cedSWang Nan 
1124*f5a08cedSWang Nan __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(comm,
1125*f5a08cedSWang Nan 	__NON_SAMPLE_ADD_FIELD(u32, pid);
1126*f5a08cedSWang Nan 	__NON_SAMPLE_ADD_FIELD(u32, tid);
1127*f5a08cedSWang Nan 	__NON_SAMPLE_ADD_FIELD(string, comm);
1128*f5a08cedSWang Nan )
1129*f5a08cedSWang Nan 
1130*f5a08cedSWang Nan #undef __NON_SAMPLE_ADD_FIELD
1131*f5a08cedSWang Nan #undef __FUNC_ADD_NON_SAMPLE_EVENT_CLASS
1132*f5a08cedSWang Nan 
1133*f5a08cedSWang Nan static int setup_non_sample_events(struct ctf_writer *cw,
1134*f5a08cedSWang Nan 				   struct perf_session *session __maybe_unused)
1135*f5a08cedSWang Nan {
1136*f5a08cedSWang Nan 	int ret;
1137*f5a08cedSWang Nan 
1138*f5a08cedSWang Nan 	ret = add_comm_event(cw);
1139*f5a08cedSWang Nan 	if (ret)
1140*f5a08cedSWang Nan 		return ret;
1141*f5a08cedSWang Nan 	return 0;
1142*f5a08cedSWang Nan }
1143*f5a08cedSWang Nan 
11445141d735SWang Nan static void cleanup_events(struct perf_session *session)
11455141d735SWang Nan {
11465141d735SWang Nan 	struct perf_evlist *evlist = session->evlist;
11475141d735SWang Nan 	struct perf_evsel *evsel;
11485141d735SWang Nan 
1149e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
11505141d735SWang Nan 		struct evsel_priv *priv;
11515141d735SWang Nan 
11525141d735SWang Nan 		priv = evsel->priv;
11535141d735SWang Nan 		bt_ctf_event_class_put(priv->event_class);
11545141d735SWang Nan 		zfree(&evsel->priv);
11555141d735SWang Nan 	}
11565141d735SWang Nan 
11575141d735SWang Nan 	perf_evlist__delete(evlist);
11585141d735SWang Nan 	session->evlist = NULL;
11595141d735SWang Nan }
11605141d735SWang Nan 
116190e129ffSSebastian Andrzej Siewior static int setup_streams(struct ctf_writer *cw, struct perf_session *session)
116290e129ffSSebastian Andrzej Siewior {
116390e129ffSSebastian Andrzej Siewior 	struct ctf_stream **stream;
116490e129ffSSebastian Andrzej Siewior 	struct perf_header *ph = &session->header;
116590e129ffSSebastian Andrzej Siewior 	int ncpus;
116690e129ffSSebastian Andrzej Siewior 
116790e129ffSSebastian Andrzej Siewior 	/*
116890e129ffSSebastian Andrzej Siewior 	 * Try to get the number of cpus used in the data file,
116990e129ffSSebastian Andrzej Siewior 	 * if not present fallback to the MAX_CPUS.
117090e129ffSSebastian Andrzej Siewior 	 */
117190e129ffSSebastian Andrzej Siewior 	ncpus = ph->env.nr_cpus_avail ?: MAX_CPUS;
117290e129ffSSebastian Andrzej Siewior 
117390e129ffSSebastian Andrzej Siewior 	stream = zalloc(sizeof(*stream) * ncpus);
117490e129ffSSebastian Andrzej Siewior 	if (!stream) {
117590e129ffSSebastian Andrzej Siewior 		pr_err("Failed to allocate streams.\n");
117690e129ffSSebastian Andrzej Siewior 		return -ENOMEM;
117790e129ffSSebastian Andrzej Siewior 	}
117890e129ffSSebastian Andrzej Siewior 
117990e129ffSSebastian Andrzej Siewior 	cw->stream     = stream;
118090e129ffSSebastian Andrzej Siewior 	cw->stream_cnt = ncpus;
118190e129ffSSebastian Andrzej Siewior 	return 0;
118290e129ffSSebastian Andrzej Siewior }
118390e129ffSSebastian Andrzej Siewior 
118490e129ffSSebastian Andrzej Siewior static void free_streams(struct ctf_writer *cw)
118590e129ffSSebastian Andrzej Siewior {
118690e129ffSSebastian Andrzej Siewior 	int cpu;
118790e129ffSSebastian Andrzej Siewior 
118890e129ffSSebastian Andrzej Siewior 	for (cpu = 0; cpu < cw->stream_cnt; cpu++)
118990e129ffSSebastian Andrzej Siewior 		ctf_stream__delete(cw->stream[cpu]);
119090e129ffSSebastian Andrzej Siewior 
119190e129ffSSebastian Andrzej Siewior 	free(cw->stream);
119290e129ffSSebastian Andrzej Siewior }
119390e129ffSSebastian Andrzej Siewior 
1194edbe9817SJiri Olsa static int ctf_writer__setup_env(struct ctf_writer *cw,
1195edbe9817SJiri Olsa 				 struct perf_session *session)
1196edbe9817SJiri Olsa {
1197edbe9817SJiri Olsa 	struct perf_header *header = &session->header;
1198edbe9817SJiri Olsa 	struct bt_ctf_writer *writer = cw->writer;
1199edbe9817SJiri Olsa 
1200edbe9817SJiri Olsa #define ADD(__n, __v)							\
1201edbe9817SJiri Olsa do {									\
1202edbe9817SJiri Olsa 	if (bt_ctf_writer_add_environment_field(writer, __n, __v))	\
1203edbe9817SJiri Olsa 		return -1;						\
1204edbe9817SJiri Olsa } while (0)
1205edbe9817SJiri Olsa 
1206edbe9817SJiri Olsa 	ADD("host",    header->env.hostname);
1207edbe9817SJiri Olsa 	ADD("sysname", "Linux");
1208edbe9817SJiri Olsa 	ADD("release", header->env.os_release);
1209edbe9817SJiri Olsa 	ADD("version", header->env.version);
1210edbe9817SJiri Olsa 	ADD("machine", header->env.arch);
1211edbe9817SJiri Olsa 	ADD("domain", "kernel");
1212edbe9817SJiri Olsa 	ADD("tracer_name", "perf");
1213edbe9817SJiri Olsa 
1214edbe9817SJiri Olsa #undef ADD
1215edbe9817SJiri Olsa 	return 0;
1216edbe9817SJiri Olsa }
1217edbe9817SJiri Olsa 
1218edbe9817SJiri Olsa static int ctf_writer__setup_clock(struct ctf_writer *cw)
1219edbe9817SJiri Olsa {
1220edbe9817SJiri Olsa 	struct bt_ctf_clock *clock = cw->clock;
1221edbe9817SJiri Olsa 
1222edbe9817SJiri Olsa 	bt_ctf_clock_set_description(clock, "perf clock");
1223edbe9817SJiri Olsa 
1224edbe9817SJiri Olsa #define SET(__n, __v)				\
1225edbe9817SJiri Olsa do {						\
1226edbe9817SJiri Olsa 	if (bt_ctf_clock_set_##__n(clock, __v))	\
1227edbe9817SJiri Olsa 		return -1;			\
1228edbe9817SJiri Olsa } while (0)
1229edbe9817SJiri Olsa 
1230edbe9817SJiri Olsa 	SET(frequency,   1000000000);
1231edbe9817SJiri Olsa 	SET(offset_s,    0);
1232edbe9817SJiri Olsa 	SET(offset,      0);
1233edbe9817SJiri Olsa 	SET(precision,   10);
1234edbe9817SJiri Olsa 	SET(is_absolute, 0);
1235edbe9817SJiri Olsa 
1236edbe9817SJiri Olsa #undef SET
1237edbe9817SJiri Olsa 	return 0;
1238edbe9817SJiri Olsa }
1239edbe9817SJiri Olsa 
1240edbe9817SJiri Olsa static struct bt_ctf_field_type *create_int_type(int size, bool sign, bool hex)
1241edbe9817SJiri Olsa {
1242edbe9817SJiri Olsa 	struct bt_ctf_field_type *type;
1243edbe9817SJiri Olsa 
1244edbe9817SJiri Olsa 	type = bt_ctf_field_type_integer_create(size);
1245edbe9817SJiri Olsa 	if (!type)
1246edbe9817SJiri Olsa 		return NULL;
1247edbe9817SJiri Olsa 
1248edbe9817SJiri Olsa 	if (sign &&
1249edbe9817SJiri Olsa 	    bt_ctf_field_type_integer_set_signed(type, 1))
1250edbe9817SJiri Olsa 		goto err;
1251edbe9817SJiri Olsa 
1252edbe9817SJiri Olsa 	if (hex &&
1253edbe9817SJiri Olsa 	    bt_ctf_field_type_integer_set_base(type, BT_CTF_INTEGER_BASE_HEXADECIMAL))
1254edbe9817SJiri Olsa 		goto err;
1255edbe9817SJiri Olsa 
1256f8dd2d5fSWang Nan #if __BYTE_ORDER == __BIG_ENDIAN
1257f8dd2d5fSWang Nan 	bt_ctf_field_type_set_byte_order(type, BT_CTF_BYTE_ORDER_BIG_ENDIAN);
1258f8dd2d5fSWang Nan #else
1259f8dd2d5fSWang Nan 	bt_ctf_field_type_set_byte_order(type, BT_CTF_BYTE_ORDER_LITTLE_ENDIAN);
1260f8dd2d5fSWang Nan #endif
1261f8dd2d5fSWang Nan 
1262edbe9817SJiri Olsa 	pr2("Created type: INTEGER %d-bit %ssigned %s\n",
1263edbe9817SJiri Olsa 	    size, sign ? "un" : "", hex ? "hex" : "");
1264edbe9817SJiri Olsa 	return type;
1265edbe9817SJiri Olsa 
1266edbe9817SJiri Olsa err:
1267edbe9817SJiri Olsa 	bt_ctf_field_type_put(type);
1268edbe9817SJiri Olsa 	return NULL;
1269edbe9817SJiri Olsa }
1270edbe9817SJiri Olsa 
1271edbe9817SJiri Olsa static void ctf_writer__cleanup_data(struct ctf_writer *cw)
1272edbe9817SJiri Olsa {
1273edbe9817SJiri Olsa 	unsigned int i;
1274edbe9817SJiri Olsa 
1275edbe9817SJiri Olsa 	for (i = 0; i < ARRAY_SIZE(cw->data.array); i++)
1276edbe9817SJiri Olsa 		bt_ctf_field_type_put(cw->data.array[i]);
1277edbe9817SJiri Olsa }
1278edbe9817SJiri Olsa 
1279edbe9817SJiri Olsa static int ctf_writer__init_data(struct ctf_writer *cw)
1280edbe9817SJiri Olsa {
1281edbe9817SJiri Olsa #define CREATE_INT_TYPE(type, size, sign, hex)		\
1282edbe9817SJiri Olsa do {							\
1283edbe9817SJiri Olsa 	(type) = create_int_type(size, sign, hex);	\
1284edbe9817SJiri Olsa 	if (!(type))					\
1285edbe9817SJiri Olsa 		goto err;				\
1286edbe9817SJiri Olsa } while (0)
1287edbe9817SJiri Olsa 
1288edbe9817SJiri Olsa 	CREATE_INT_TYPE(cw->data.s64, 64, true,  false);
1289edbe9817SJiri Olsa 	CREATE_INT_TYPE(cw->data.u64, 64, false, false);
1290edbe9817SJiri Olsa 	CREATE_INT_TYPE(cw->data.s32, 32, true,  false);
1291edbe9817SJiri Olsa 	CREATE_INT_TYPE(cw->data.u32, 32, false, false);
129226812d46SWang Nan 	CREATE_INT_TYPE(cw->data.u32_hex, 32, false, true);
1293edbe9817SJiri Olsa 	CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true);
1294edbe9817SJiri Olsa 
1295edbe9817SJiri Olsa 	cw->data.string  = bt_ctf_field_type_string_create();
1296edbe9817SJiri Olsa 	if (cw->data.string)
1297edbe9817SJiri Olsa 		return 0;
1298edbe9817SJiri Olsa 
1299edbe9817SJiri Olsa err:
1300edbe9817SJiri Olsa 	ctf_writer__cleanup_data(cw);
1301edbe9817SJiri Olsa 	pr_err("Failed to create data types.\n");
1302edbe9817SJiri Olsa 	return -1;
1303edbe9817SJiri Olsa }
1304edbe9817SJiri Olsa 
1305edbe9817SJiri Olsa static void ctf_writer__cleanup(struct ctf_writer *cw)
1306edbe9817SJiri Olsa {
1307edbe9817SJiri Olsa 	ctf_writer__cleanup_data(cw);
1308edbe9817SJiri Olsa 
1309edbe9817SJiri Olsa 	bt_ctf_clock_put(cw->clock);
131090e129ffSSebastian Andrzej Siewior 	free_streams(cw);
1311edbe9817SJiri Olsa 	bt_ctf_stream_class_put(cw->stream_class);
1312edbe9817SJiri Olsa 	bt_ctf_writer_put(cw->writer);
1313edbe9817SJiri Olsa 
1314edbe9817SJiri Olsa 	/* and NULL all the pointers */
1315edbe9817SJiri Olsa 	memset(cw, 0, sizeof(*cw));
1316edbe9817SJiri Olsa }
1317edbe9817SJiri Olsa 
1318edbe9817SJiri Olsa static int ctf_writer__init(struct ctf_writer *cw, const char *path)
1319edbe9817SJiri Olsa {
1320edbe9817SJiri Olsa 	struct bt_ctf_writer		*writer;
1321edbe9817SJiri Olsa 	struct bt_ctf_stream_class	*stream_class;
1322edbe9817SJiri Olsa 	struct bt_ctf_clock		*clock;
132390e129ffSSebastian Andrzej Siewior 	struct bt_ctf_field_type	*pkt_ctx_type;
132490e129ffSSebastian Andrzej Siewior 	int				ret;
1325edbe9817SJiri Olsa 
1326edbe9817SJiri Olsa 	/* CTF writer */
1327edbe9817SJiri Olsa 	writer = bt_ctf_writer_create(path);
1328edbe9817SJiri Olsa 	if (!writer)
1329edbe9817SJiri Olsa 		goto err;
1330edbe9817SJiri Olsa 
1331edbe9817SJiri Olsa 	cw->writer = writer;
1332edbe9817SJiri Olsa 
1333edbe9817SJiri Olsa 	/* CTF clock */
1334edbe9817SJiri Olsa 	clock = bt_ctf_clock_create("perf_clock");
1335edbe9817SJiri Olsa 	if (!clock) {
1336edbe9817SJiri Olsa 		pr("Failed to create CTF clock.\n");
1337edbe9817SJiri Olsa 		goto err_cleanup;
1338edbe9817SJiri Olsa 	}
1339edbe9817SJiri Olsa 
1340edbe9817SJiri Olsa 	cw->clock = clock;
1341edbe9817SJiri Olsa 
1342edbe9817SJiri Olsa 	if (ctf_writer__setup_clock(cw)) {
1343edbe9817SJiri Olsa 		pr("Failed to setup CTF clock.\n");
1344edbe9817SJiri Olsa 		goto err_cleanup;
1345edbe9817SJiri Olsa 	}
1346edbe9817SJiri Olsa 
1347edbe9817SJiri Olsa 	/* CTF stream class */
1348edbe9817SJiri Olsa 	stream_class = bt_ctf_stream_class_create("perf_stream");
1349edbe9817SJiri Olsa 	if (!stream_class) {
1350edbe9817SJiri Olsa 		pr("Failed to create CTF stream class.\n");
1351edbe9817SJiri Olsa 		goto err_cleanup;
1352edbe9817SJiri Olsa 	}
1353edbe9817SJiri Olsa 
1354edbe9817SJiri Olsa 	cw->stream_class = stream_class;
1355edbe9817SJiri Olsa 
1356edbe9817SJiri Olsa 	/* CTF clock stream setup */
1357edbe9817SJiri Olsa 	if (bt_ctf_stream_class_set_clock(stream_class, clock)) {
1358edbe9817SJiri Olsa 		pr("Failed to assign CTF clock to stream class.\n");
1359edbe9817SJiri Olsa 		goto err_cleanup;
1360edbe9817SJiri Olsa 	}
1361edbe9817SJiri Olsa 
1362edbe9817SJiri Olsa 	if (ctf_writer__init_data(cw))
1363edbe9817SJiri Olsa 		goto err_cleanup;
1364edbe9817SJiri Olsa 
136590e129ffSSebastian Andrzej Siewior 	/* Add cpu_id for packet context */
136690e129ffSSebastian Andrzej Siewior 	pkt_ctx_type = bt_ctf_stream_class_get_packet_context_type(stream_class);
136790e129ffSSebastian Andrzej Siewior 	if (!pkt_ctx_type)
1368edbe9817SJiri Olsa 		goto err_cleanup;
1369edbe9817SJiri Olsa 
137090e129ffSSebastian Andrzej Siewior 	ret = bt_ctf_field_type_structure_add_field(pkt_ctx_type, cw->data.u32, "cpu_id");
137190e129ffSSebastian Andrzej Siewior 	bt_ctf_field_type_put(pkt_ctx_type);
137290e129ffSSebastian Andrzej Siewior 	if (ret)
137390e129ffSSebastian Andrzej Siewior 		goto err_cleanup;
1374edbe9817SJiri Olsa 
1375edbe9817SJiri Olsa 	/* CTF clock writer setup */
1376edbe9817SJiri Olsa 	if (bt_ctf_writer_add_clock(writer, clock)) {
1377edbe9817SJiri Olsa 		pr("Failed to assign CTF clock to writer.\n");
1378edbe9817SJiri Olsa 		goto err_cleanup;
1379edbe9817SJiri Olsa 	}
1380edbe9817SJiri Olsa 
1381edbe9817SJiri Olsa 	return 0;
1382edbe9817SJiri Olsa 
1383edbe9817SJiri Olsa err_cleanup:
1384edbe9817SJiri Olsa 	ctf_writer__cleanup(cw);
1385edbe9817SJiri Olsa err:
1386edbe9817SJiri Olsa 	pr_err("Failed to setup CTF writer.\n");
1387edbe9817SJiri Olsa 	return -1;
1388edbe9817SJiri Olsa }
1389edbe9817SJiri Olsa 
139090e129ffSSebastian Andrzej Siewior static int ctf_writer__flush_streams(struct ctf_writer *cw)
139190e129ffSSebastian Andrzej Siewior {
139290e129ffSSebastian Andrzej Siewior 	int cpu, ret = 0;
139390e129ffSSebastian Andrzej Siewior 
139490e129ffSSebastian Andrzej Siewior 	for (cpu = 0; cpu < cw->stream_cnt && !ret; cpu++)
139590e129ffSSebastian Andrzej Siewior 		ret = ctf_stream__flush(cw->stream[cpu]);
139690e129ffSSebastian Andrzej Siewior 
139790e129ffSSebastian Andrzej Siewior 	return ret;
139890e129ffSSebastian Andrzej Siewior }
139990e129ffSSebastian Andrzej Siewior 
14008fa46753SJiri Olsa static int convert__config(const char *var, const char *value, void *cb)
14018fa46753SJiri Olsa {
14028fa46753SJiri Olsa 	struct convert *c = cb;
14038fa46753SJiri Olsa 
14048fa46753SJiri Olsa 	if (!strcmp(var, "convert.queue-size")) {
14058fa46753SJiri Olsa 		c->queue_size = perf_config_u64(var, value);
14068fa46753SJiri Olsa 		return 0;
14078fa46753SJiri Olsa 	}
14088fa46753SJiri Olsa 
1409b8cbb349SWang Nan 	return 0;
14108fa46753SJiri Olsa }
14118fa46753SJiri Olsa 
14123275f68eSWang Nan int bt_convert__perf2ctf(const char *input, const char *path,
14133275f68eSWang Nan 			 struct perf_data_convert_opts *opts)
1414edbe9817SJiri Olsa {
1415edbe9817SJiri Olsa 	struct perf_session *session;
1416edbe9817SJiri Olsa 	struct perf_data_file file = {
1417edbe9817SJiri Olsa 		.path = input,
1418edbe9817SJiri Olsa 		.mode = PERF_DATA_MODE_READ,
14193275f68eSWang Nan 		.force = opts->force,
1420edbe9817SJiri Olsa 	};
1421edbe9817SJiri Olsa 	struct convert c = {
1422edbe9817SJiri Olsa 		.tool = {
1423edbe9817SJiri Olsa 			.sample          = process_sample_event,
1424edbe9817SJiri Olsa 			.mmap            = perf_event__process_mmap,
1425edbe9817SJiri Olsa 			.mmap2           = perf_event__process_mmap2,
1426edbe9817SJiri Olsa 			.comm            = perf_event__process_comm,
1427edbe9817SJiri Olsa 			.exit            = perf_event__process_exit,
1428edbe9817SJiri Olsa 			.fork            = perf_event__process_fork,
1429edbe9817SJiri Olsa 			.lost            = perf_event__process_lost,
1430edbe9817SJiri Olsa 			.tracing_data    = perf_event__process_tracing_data,
1431edbe9817SJiri Olsa 			.build_id        = perf_event__process_build_id,
1432edbe9817SJiri Olsa 			.ordered_events  = true,
1433edbe9817SJiri Olsa 			.ordering_requires_timestamps = true,
1434edbe9817SJiri Olsa 		},
1435edbe9817SJiri Olsa 	};
1436edbe9817SJiri Olsa 	struct ctf_writer *cw = &c.writer;
1437edbe9817SJiri Olsa 	int err = -1;
1438edbe9817SJiri Olsa 
1439*f5a08cedSWang Nan 	if (opts->all)
1440*f5a08cedSWang Nan 		c.tool.comm = process_comm_event;
1441*f5a08cedSWang Nan 
14428fa46753SJiri Olsa 	perf_config(convert__config, &c);
14438fa46753SJiri Olsa 
1444edbe9817SJiri Olsa 	/* CTF writer */
1445edbe9817SJiri Olsa 	if (ctf_writer__init(cw, path))
1446edbe9817SJiri Olsa 		return -1;
1447edbe9817SJiri Olsa 
1448edbe9817SJiri Olsa 	/* perf.data session */
1449b7b61cbeSArnaldo Carvalho de Melo 	session = perf_session__new(&file, 0, &c.tool);
1450edbe9817SJiri Olsa 	if (!session)
1451edbe9817SJiri Olsa 		goto free_writer;
1452edbe9817SJiri Olsa 
14538fa46753SJiri Olsa 	if (c.queue_size) {
14548fa46753SJiri Olsa 		ordered_events__set_alloc_size(&session->ordered_events,
14558fa46753SJiri Olsa 					       c.queue_size);
14568fa46753SJiri Olsa 	}
14578fa46753SJiri Olsa 
1458edbe9817SJiri Olsa 	/* CTF writer env/clock setup  */
1459edbe9817SJiri Olsa 	if (ctf_writer__setup_env(cw, session))
1460edbe9817SJiri Olsa 		goto free_session;
1461edbe9817SJiri Olsa 
1462edbe9817SJiri Olsa 	/* CTF events setup */
1463edbe9817SJiri Olsa 	if (setup_events(cw, session))
1464edbe9817SJiri Olsa 		goto free_session;
1465edbe9817SJiri Olsa 
1466*f5a08cedSWang Nan 	if (opts->all && setup_non_sample_events(cw, session))
1467*f5a08cedSWang Nan 		goto free_session;
1468*f5a08cedSWang Nan 
146990e129ffSSebastian Andrzej Siewior 	if (setup_streams(cw, session))
147090e129ffSSebastian Andrzej Siewior 		goto free_session;
147190e129ffSSebastian Andrzej Siewior 
1472b7b61cbeSArnaldo Carvalho de Melo 	err = perf_session__process_events(session);
1473edbe9817SJiri Olsa 	if (!err)
147490e129ffSSebastian Andrzej Siewior 		err = ctf_writer__flush_streams(cw);
1475c2141055SHe Kuang 	else
1476c2141055SHe Kuang 		pr_err("Error during conversion.\n");
1477edbe9817SJiri Olsa 
1478edbe9817SJiri Olsa 	fprintf(stderr,
1479edbe9817SJiri Olsa 		"[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
1480edbe9817SJiri Olsa 		file.path, path);
1481edbe9817SJiri Olsa 
1482edbe9817SJiri Olsa 	fprintf(stderr,
14838ee4c46cSWang Nan 		"[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
1484edbe9817SJiri Olsa 		(double) c.events_size / 1024.0 / 1024.0,
1485edbe9817SJiri Olsa 		c.events_count);
1486edbe9817SJiri Olsa 
14878ee4c46cSWang Nan 	if (!c.non_sample_count)
14888ee4c46cSWang Nan 		fprintf(stderr, ") ]\n");
14898ee4c46cSWang Nan 	else
14908ee4c46cSWang Nan 		fprintf(stderr, ", %" PRIu64 " non-samples) ]\n", c.non_sample_count);
14918ee4c46cSWang Nan 
14925141d735SWang Nan 	cleanup_events(session);
1493c2141055SHe Kuang 	perf_session__delete(session);
1494c2141055SHe Kuang 	ctf_writer__cleanup(cw);
1495c2141055SHe Kuang 
1496c2141055SHe Kuang 	return err;
1497c2141055SHe Kuang 
1498edbe9817SJiri Olsa free_session:
1499edbe9817SJiri Olsa 	perf_session__delete(session);
1500edbe9817SJiri Olsa free_writer:
1501edbe9817SJiri Olsa 	ctf_writer__cleanup(cw);
1502c2141055SHe Kuang 	pr_err("Error during conversion setup.\n");
1503edbe9817SJiri Olsa 	return err;
1504edbe9817SJiri Olsa }
1505