xref: /linux/tools/perf/util/data-convert-bt.c (revision 5ea5888b2fbf5b230da62b2a21c8247bebb6c9cf)
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"
29edbe9817SJiri Olsa 
30edbe9817SJiri Olsa #define pr_N(n, fmt, ...) \
31edbe9817SJiri Olsa 	eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
32edbe9817SJiri Olsa 
33edbe9817SJiri Olsa #define pr(fmt, ...)  pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
34edbe9817SJiri Olsa #define pr2(fmt, ...) pr_N(2, pr_fmt(fmt), ##__VA_ARGS__)
35edbe9817SJiri Olsa 
36edbe9817SJiri Olsa #define pr_time2(t, fmt, ...) pr_time_N(2, debug_data_convert, t, pr_fmt(fmt), ##__VA_ARGS__)
37edbe9817SJiri Olsa 
38edbe9817SJiri Olsa struct evsel_priv {
39edbe9817SJiri Olsa 	struct bt_ctf_event_class *event_class;
40edbe9817SJiri Olsa };
41edbe9817SJiri Olsa 
4290e129ffSSebastian Andrzej Siewior #define MAX_CPUS	4096
4390e129ffSSebastian Andrzej Siewior 
4490e129ffSSebastian Andrzej Siewior struct ctf_stream {
4590e129ffSSebastian Andrzej Siewior 	struct bt_ctf_stream *stream;
4690e129ffSSebastian Andrzej Siewior 	int cpu;
4789e5fa88SJiri Olsa 	u32 count;
4890e129ffSSebastian Andrzej Siewior };
4990e129ffSSebastian Andrzej Siewior 
50edbe9817SJiri Olsa struct ctf_writer {
51edbe9817SJiri Olsa 	/* writer primitives */
52edbe9817SJiri Olsa 	struct bt_ctf_writer		 *writer;
5390e129ffSSebastian Andrzej Siewior 	struct ctf_stream		**stream;
5490e129ffSSebastian Andrzej Siewior 	int				  stream_cnt;
55edbe9817SJiri Olsa 	struct bt_ctf_stream_class	 *stream_class;
56edbe9817SJiri Olsa 	struct bt_ctf_clock		 *clock;
57edbe9817SJiri Olsa 
58edbe9817SJiri Olsa 	/* data types */
59edbe9817SJiri Olsa 	union {
60edbe9817SJiri Olsa 		struct {
61edbe9817SJiri Olsa 			struct bt_ctf_field_type	*s64;
62edbe9817SJiri Olsa 			struct bt_ctf_field_type	*u64;
63edbe9817SJiri Olsa 			struct bt_ctf_field_type	*s32;
64edbe9817SJiri Olsa 			struct bt_ctf_field_type	*u32;
65edbe9817SJiri Olsa 			struct bt_ctf_field_type	*string;
6626812d46SWang Nan 			struct bt_ctf_field_type	*u32_hex;
67edbe9817SJiri Olsa 			struct bt_ctf_field_type	*u64_hex;
68edbe9817SJiri Olsa 		};
69edbe9817SJiri Olsa 		struct bt_ctf_field_type *array[6];
70edbe9817SJiri Olsa 	} data;
71edbe9817SJiri Olsa };
72edbe9817SJiri Olsa 
73edbe9817SJiri Olsa struct convert {
74edbe9817SJiri Olsa 	struct perf_tool	tool;
75edbe9817SJiri Olsa 	struct ctf_writer	writer;
76edbe9817SJiri Olsa 
77edbe9817SJiri Olsa 	u64			events_size;
78edbe9817SJiri Olsa 	u64			events_count;
798fa46753SJiri Olsa 
808fa46753SJiri Olsa 	/* Ordered events configured queue size. */
818fa46753SJiri Olsa 	u64			queue_size;
82edbe9817SJiri Olsa };
83edbe9817SJiri Olsa 
84edbe9817SJiri Olsa static int value_set(struct bt_ctf_field_type *type,
85edbe9817SJiri Olsa 		     struct bt_ctf_event *event,
86edbe9817SJiri Olsa 		     const char *name, u64 val)
87edbe9817SJiri Olsa {
88edbe9817SJiri Olsa 	struct bt_ctf_field *field;
89edbe9817SJiri Olsa 	bool sign = bt_ctf_field_type_integer_get_signed(type);
90edbe9817SJiri Olsa 	int ret;
91edbe9817SJiri Olsa 
92edbe9817SJiri Olsa 	field = bt_ctf_field_create(type);
93edbe9817SJiri Olsa 	if (!field) {
94edbe9817SJiri Olsa 		pr_err("failed to create a field %s\n", name);
95edbe9817SJiri Olsa 		return -1;
96edbe9817SJiri Olsa 	}
97edbe9817SJiri Olsa 
98edbe9817SJiri Olsa 	if (sign) {
99edbe9817SJiri Olsa 		ret = bt_ctf_field_signed_integer_set_value(field, val);
100edbe9817SJiri Olsa 		if (ret) {
101edbe9817SJiri Olsa 			pr_err("failed to set field value %s\n", name);
102edbe9817SJiri Olsa 			goto err;
103edbe9817SJiri Olsa 		}
104edbe9817SJiri Olsa 	} else {
105edbe9817SJiri Olsa 		ret = bt_ctf_field_unsigned_integer_set_value(field, val);
106edbe9817SJiri Olsa 		if (ret) {
107edbe9817SJiri Olsa 			pr_err("failed to set field value %s\n", name);
108edbe9817SJiri Olsa 			goto err;
109edbe9817SJiri Olsa 		}
110edbe9817SJiri Olsa 	}
111edbe9817SJiri Olsa 
112edbe9817SJiri Olsa 	ret = bt_ctf_event_set_payload(event, name, field);
113edbe9817SJiri Olsa 	if (ret) {
114edbe9817SJiri Olsa 		pr_err("failed to set payload %s\n", name);
115edbe9817SJiri Olsa 		goto err;
116edbe9817SJiri Olsa 	}
117edbe9817SJiri Olsa 
118edbe9817SJiri Olsa 	pr2("  SET [%s = %" PRIu64 "]\n", name, val);
119edbe9817SJiri Olsa 
120edbe9817SJiri Olsa err:
121edbe9817SJiri Olsa 	bt_ctf_field_put(field);
122edbe9817SJiri Olsa 	return ret;
123edbe9817SJiri Olsa }
124edbe9817SJiri Olsa 
125edbe9817SJiri Olsa #define __FUNC_VALUE_SET(_name, _val_type)				\
126edbe9817SJiri Olsa static __maybe_unused int value_set_##_name(struct ctf_writer *cw,	\
127edbe9817SJiri Olsa 			     struct bt_ctf_event *event,		\
128edbe9817SJiri Olsa 			     const char *name,				\
129edbe9817SJiri Olsa 			     _val_type val)				\
130edbe9817SJiri Olsa {									\
131edbe9817SJiri Olsa 	struct bt_ctf_field_type *type = cw->data._name;		\
132edbe9817SJiri Olsa 	return value_set(type, event, name, (u64) val);			\
133edbe9817SJiri Olsa }
134edbe9817SJiri Olsa 
135edbe9817SJiri Olsa #define FUNC_VALUE_SET(_name) __FUNC_VALUE_SET(_name, _name)
136edbe9817SJiri Olsa 
137edbe9817SJiri Olsa FUNC_VALUE_SET(s32)
138edbe9817SJiri Olsa FUNC_VALUE_SET(u32)
139edbe9817SJiri Olsa FUNC_VALUE_SET(s64)
140edbe9817SJiri Olsa FUNC_VALUE_SET(u64)
141edbe9817SJiri Olsa __FUNC_VALUE_SET(u64_hex, u64)
142edbe9817SJiri Olsa 
14369364727SSebastian Andrzej Siewior static struct bt_ctf_field_type*
14469364727SSebastian Andrzej Siewior get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
14569364727SSebastian Andrzej Siewior {
14669364727SSebastian Andrzej Siewior 	unsigned long flags = field->flags;
14769364727SSebastian Andrzej Siewior 
14869364727SSebastian Andrzej Siewior 	if (flags & FIELD_IS_STRING)
14969364727SSebastian Andrzej Siewior 		return cw->data.string;
15069364727SSebastian Andrzej Siewior 
15169364727SSebastian Andrzej Siewior 	if (!(flags & FIELD_IS_SIGNED)) {
15269364727SSebastian Andrzej Siewior 		/* unsigned long are mostly pointers */
15369364727SSebastian Andrzej Siewior 		if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER)
15469364727SSebastian Andrzej Siewior 			return cw->data.u64_hex;
15569364727SSebastian Andrzej Siewior 	}
15669364727SSebastian Andrzej Siewior 
15769364727SSebastian Andrzej Siewior 	if (flags & FIELD_IS_SIGNED) {
15869364727SSebastian Andrzej Siewior 		if (field->size == 8)
15969364727SSebastian Andrzej Siewior 			return cw->data.s64;
16069364727SSebastian Andrzej Siewior 		else
16169364727SSebastian Andrzej Siewior 			return cw->data.s32;
16269364727SSebastian Andrzej Siewior 	}
16369364727SSebastian Andrzej Siewior 
16469364727SSebastian Andrzej Siewior 	if (field->size == 8)
16569364727SSebastian Andrzej Siewior 		return cw->data.u64;
16669364727SSebastian Andrzej Siewior 	else
16769364727SSebastian Andrzej Siewior 		return cw->data.u32;
16869364727SSebastian Andrzej Siewior }
16969364727SSebastian Andrzej Siewior 
170d4ae4213SWang Nan static unsigned long long adjust_signedness(unsigned long long value_int, int size)
171d4ae4213SWang Nan {
172d4ae4213SWang Nan 	unsigned long long value_mask;
173d4ae4213SWang Nan 
174d4ae4213SWang Nan 	/*
175d4ae4213SWang Nan 	 * value_mask = (1 << (size * 8 - 1)) - 1.
176d4ae4213SWang Nan 	 * Directly set value_mask for code readers.
177d4ae4213SWang Nan 	 */
178d4ae4213SWang Nan 	switch (size) {
179d4ae4213SWang Nan 	case 1:
180d4ae4213SWang Nan 		value_mask = 0x7fULL;
181d4ae4213SWang Nan 		break;
182d4ae4213SWang Nan 	case 2:
183d4ae4213SWang Nan 		value_mask = 0x7fffULL;
184d4ae4213SWang Nan 		break;
185d4ae4213SWang Nan 	case 4:
186d4ae4213SWang Nan 		value_mask = 0x7fffffffULL;
187d4ae4213SWang Nan 		break;
188d4ae4213SWang Nan 	case 8:
189d4ae4213SWang Nan 		/*
190d4ae4213SWang Nan 		 * For 64 bit value, return it self. There is no need
191d4ae4213SWang Nan 		 * to fill high bit.
192d4ae4213SWang Nan 		 */
193d4ae4213SWang Nan 		/* Fall through */
194d4ae4213SWang Nan 	default:
195d4ae4213SWang Nan 		/* BUG! */
196d4ae4213SWang Nan 		return value_int;
197d4ae4213SWang Nan 	}
198d4ae4213SWang Nan 
199d4ae4213SWang Nan 	/* If it is a positive value, don't adjust. */
200d4ae4213SWang Nan 	if ((value_int & (~0ULL - value_mask)) == 0)
201d4ae4213SWang Nan 		return value_int;
202d4ae4213SWang Nan 
203d4ae4213SWang Nan 	/* Fill upper part of value_int with 1 to make it a negative long long. */
204d4ae4213SWang Nan 	return (value_int & value_mask) | ~value_mask;
205d4ae4213SWang Nan }
206d4ae4213SWang Nan 
207*5ea5888bSWang Nan static int string_set_value(struct bt_ctf_field *field, const char *string)
208*5ea5888bSWang Nan {
209*5ea5888bSWang Nan 	char *buffer = NULL;
210*5ea5888bSWang Nan 	size_t len = strlen(string), i, p;
211*5ea5888bSWang Nan 	int err;
212*5ea5888bSWang Nan 
213*5ea5888bSWang Nan 	for (i = p = 0; i < len; i++, p++) {
214*5ea5888bSWang Nan 		if (isprint(string[i])) {
215*5ea5888bSWang Nan 			if (!buffer)
216*5ea5888bSWang Nan 				continue;
217*5ea5888bSWang Nan 			buffer[p] = string[i];
218*5ea5888bSWang Nan 		} else {
219*5ea5888bSWang Nan 			char numstr[5];
220*5ea5888bSWang Nan 
221*5ea5888bSWang Nan 			snprintf(numstr, sizeof(numstr), "\\x%02x",
222*5ea5888bSWang Nan 				 (unsigned int)(string[i]) & 0xff);
223*5ea5888bSWang Nan 
224*5ea5888bSWang Nan 			if (!buffer) {
225*5ea5888bSWang Nan 				buffer = zalloc(i + (len - i) * 4 + 2);
226*5ea5888bSWang Nan 				if (!buffer) {
227*5ea5888bSWang Nan 					pr_err("failed to set unprintable string '%s'\n", string);
228*5ea5888bSWang Nan 					return bt_ctf_field_string_set_value(field, "UNPRINTABLE-STRING");
229*5ea5888bSWang Nan 				}
230*5ea5888bSWang Nan 				if (i > 0)
231*5ea5888bSWang Nan 					strncpy(buffer, string, i);
232*5ea5888bSWang Nan 			}
233*5ea5888bSWang Nan 			strncat(buffer + p, numstr, 4);
234*5ea5888bSWang Nan 			p += 3;
235*5ea5888bSWang Nan 		}
236*5ea5888bSWang Nan 	}
237*5ea5888bSWang Nan 
238*5ea5888bSWang Nan 	if (!buffer)
239*5ea5888bSWang Nan 		return bt_ctf_field_string_set_value(field, string);
240*5ea5888bSWang Nan 	err = bt_ctf_field_string_set_value(field, buffer);
241*5ea5888bSWang Nan 	free(buffer);
242*5ea5888bSWang Nan 	return err;
243*5ea5888bSWang Nan }
244*5ea5888bSWang Nan 
24569364727SSebastian Andrzej Siewior static int add_tracepoint_field_value(struct ctf_writer *cw,
24669364727SSebastian Andrzej Siewior 				      struct bt_ctf_event_class *event_class,
24769364727SSebastian Andrzej Siewior 				      struct bt_ctf_event *event,
24869364727SSebastian Andrzej Siewior 				      struct perf_sample *sample,
24969364727SSebastian Andrzej Siewior 				      struct format_field *fmtf)
25069364727SSebastian Andrzej Siewior {
25169364727SSebastian Andrzej Siewior 	struct bt_ctf_field_type *type;
25269364727SSebastian Andrzej Siewior 	struct bt_ctf_field *array_field;
25369364727SSebastian Andrzej Siewior 	struct bt_ctf_field *field;
25469364727SSebastian Andrzej Siewior 	const char *name = fmtf->name;
25569364727SSebastian Andrzej Siewior 	void *data = sample->raw_data;
25669364727SSebastian Andrzej Siewior 	unsigned long flags = fmtf->flags;
25769364727SSebastian Andrzej Siewior 	unsigned int n_items;
25869364727SSebastian Andrzej Siewior 	unsigned int i;
25969364727SSebastian Andrzej Siewior 	unsigned int offset;
26069364727SSebastian Andrzej Siewior 	unsigned int len;
26169364727SSebastian Andrzej Siewior 	int ret;
26269364727SSebastian Andrzej Siewior 
263e0a7cce5SWang Nan 	name = fmtf->alias;
26469364727SSebastian Andrzej Siewior 	offset = fmtf->offset;
26569364727SSebastian Andrzej Siewior 	len = fmtf->size;
26669364727SSebastian Andrzej Siewior 	if (flags & FIELD_IS_STRING)
26769364727SSebastian Andrzej Siewior 		flags &= ~FIELD_IS_ARRAY;
26869364727SSebastian Andrzej Siewior 
26969364727SSebastian Andrzej Siewior 	if (flags & FIELD_IS_DYNAMIC) {
27069364727SSebastian Andrzej Siewior 		unsigned long long tmp_val;
27169364727SSebastian Andrzej Siewior 
27269364727SSebastian Andrzej Siewior 		tmp_val = pevent_read_number(fmtf->event->pevent,
27369364727SSebastian Andrzej Siewior 				data + offset, len);
27469364727SSebastian Andrzej Siewior 		offset = tmp_val;
27569364727SSebastian Andrzej Siewior 		len = offset >> 16;
27669364727SSebastian Andrzej Siewior 		offset &= 0xffff;
27769364727SSebastian Andrzej Siewior 	}
27869364727SSebastian Andrzej Siewior 
27969364727SSebastian Andrzej Siewior 	if (flags & FIELD_IS_ARRAY) {
28069364727SSebastian Andrzej Siewior 
28169364727SSebastian Andrzej Siewior 		type = bt_ctf_event_class_get_field_by_name(
28269364727SSebastian Andrzej Siewior 				event_class, name);
28369364727SSebastian Andrzej Siewior 		array_field = bt_ctf_field_create(type);
28469364727SSebastian Andrzej Siewior 		bt_ctf_field_type_put(type);
28569364727SSebastian Andrzej Siewior 		if (!array_field) {
28669364727SSebastian Andrzej Siewior 			pr_err("Failed to create array type %s\n", name);
28769364727SSebastian Andrzej Siewior 			return -1;
28869364727SSebastian Andrzej Siewior 		}
28969364727SSebastian Andrzej Siewior 
29069364727SSebastian Andrzej Siewior 		len = fmtf->size / fmtf->arraylen;
29169364727SSebastian Andrzej Siewior 		n_items = fmtf->arraylen;
29269364727SSebastian Andrzej Siewior 	} else {
29369364727SSebastian Andrzej Siewior 		n_items = 1;
29469364727SSebastian Andrzej Siewior 		array_field = NULL;
29569364727SSebastian Andrzej Siewior 	}
29669364727SSebastian Andrzej Siewior 
29769364727SSebastian Andrzej Siewior 	type = get_tracepoint_field_type(cw, fmtf);
29869364727SSebastian Andrzej Siewior 
29969364727SSebastian Andrzej Siewior 	for (i = 0; i < n_items; i++) {
30069364727SSebastian Andrzej Siewior 		if (flags & FIELD_IS_ARRAY)
30169364727SSebastian Andrzej Siewior 			field = bt_ctf_field_array_get_field(array_field, i);
30269364727SSebastian Andrzej Siewior 		else
30369364727SSebastian Andrzej Siewior 			field = bt_ctf_field_create(type);
30469364727SSebastian Andrzej Siewior 
30569364727SSebastian Andrzej Siewior 		if (!field) {
30669364727SSebastian Andrzej Siewior 			pr_err("failed to create a field %s\n", name);
30769364727SSebastian Andrzej Siewior 			return -1;
30869364727SSebastian Andrzej Siewior 		}
30969364727SSebastian Andrzej Siewior 
31069364727SSebastian Andrzej Siewior 		if (flags & FIELD_IS_STRING)
311*5ea5888bSWang Nan 			ret = string_set_value(field, data + offset + i * len);
312d4ae4213SWang Nan 		else {
313d4ae4213SWang Nan 			unsigned long long value_int;
314d4ae4213SWang Nan 
315d4ae4213SWang Nan 			value_int = pevent_read_number(
316d4ae4213SWang Nan 					fmtf->event->pevent,
317d4ae4213SWang Nan 					data + offset + i * len, len);
318d4ae4213SWang Nan 
319d4ae4213SWang Nan 			if (!(flags & FIELD_IS_SIGNED))
32069364727SSebastian Andrzej Siewior 				ret = bt_ctf_field_unsigned_integer_set_value(
32169364727SSebastian Andrzej Siewior 						field, value_int);
32269364727SSebastian Andrzej Siewior 			else
32369364727SSebastian Andrzej Siewior 				ret = bt_ctf_field_signed_integer_set_value(
324d4ae4213SWang Nan 						field, adjust_signedness(value_int, len));
325d4ae4213SWang Nan 		}
326d4ae4213SWang Nan 
32769364727SSebastian Andrzej Siewior 		if (ret) {
32869364727SSebastian Andrzej Siewior 			pr_err("failed to set file value %s\n", name);
32969364727SSebastian Andrzej Siewior 			goto err_put_field;
33069364727SSebastian Andrzej Siewior 		}
33169364727SSebastian Andrzej Siewior 		if (!(flags & FIELD_IS_ARRAY)) {
33269364727SSebastian Andrzej Siewior 			ret = bt_ctf_event_set_payload(event, name, field);
33369364727SSebastian Andrzej Siewior 			if (ret) {
33469364727SSebastian Andrzej Siewior 				pr_err("failed to set payload %s\n", name);
33569364727SSebastian Andrzej Siewior 				goto err_put_field;
33669364727SSebastian Andrzej Siewior 			}
33769364727SSebastian Andrzej Siewior 		}
33869364727SSebastian Andrzej Siewior 		bt_ctf_field_put(field);
33969364727SSebastian Andrzej Siewior 	}
34069364727SSebastian Andrzej Siewior 	if (flags & FIELD_IS_ARRAY) {
34169364727SSebastian Andrzej Siewior 		ret = bt_ctf_event_set_payload(event, name, array_field);
34269364727SSebastian Andrzej Siewior 		if (ret) {
34369364727SSebastian Andrzej Siewior 			pr_err("Failed add payload array %s\n", name);
34469364727SSebastian Andrzej Siewior 			return -1;
34569364727SSebastian Andrzej Siewior 		}
34669364727SSebastian Andrzej Siewior 		bt_ctf_field_put(array_field);
34769364727SSebastian Andrzej Siewior 	}
34869364727SSebastian Andrzej Siewior 	return 0;
34969364727SSebastian Andrzej Siewior 
35069364727SSebastian Andrzej Siewior err_put_field:
35169364727SSebastian Andrzej Siewior 	bt_ctf_field_put(field);
35269364727SSebastian Andrzej Siewior 	return -1;
35369364727SSebastian Andrzej Siewior }
35469364727SSebastian Andrzej Siewior 
35569364727SSebastian Andrzej Siewior static int add_tracepoint_fields_values(struct ctf_writer *cw,
35669364727SSebastian Andrzej Siewior 					struct bt_ctf_event_class *event_class,
35769364727SSebastian Andrzej Siewior 					struct bt_ctf_event *event,
35869364727SSebastian Andrzej Siewior 					struct format_field *fields,
35969364727SSebastian Andrzej Siewior 					struct perf_sample *sample)
36069364727SSebastian Andrzej Siewior {
36169364727SSebastian Andrzej Siewior 	struct format_field *field;
36269364727SSebastian Andrzej Siewior 	int ret;
36369364727SSebastian Andrzej Siewior 
36469364727SSebastian Andrzej Siewior 	for (field = fields; field; field = field->next) {
36569364727SSebastian Andrzej Siewior 		ret = add_tracepoint_field_value(cw, event_class, event, sample,
36669364727SSebastian Andrzej Siewior 				field);
36769364727SSebastian Andrzej Siewior 		if (ret)
36869364727SSebastian Andrzej Siewior 			return -1;
36969364727SSebastian Andrzej Siewior 	}
37069364727SSebastian Andrzej Siewior 	return 0;
37169364727SSebastian Andrzej Siewior }
37269364727SSebastian Andrzej Siewior 
37369364727SSebastian Andrzej Siewior static int add_tracepoint_values(struct ctf_writer *cw,
37469364727SSebastian Andrzej Siewior 				 struct bt_ctf_event_class *event_class,
37569364727SSebastian Andrzej Siewior 				 struct bt_ctf_event *event,
37669364727SSebastian Andrzej Siewior 				 struct perf_evsel *evsel,
37769364727SSebastian Andrzej Siewior 				 struct perf_sample *sample)
37869364727SSebastian Andrzej Siewior {
37969364727SSebastian Andrzej Siewior 	struct format_field *common_fields = evsel->tp_format->format.common_fields;
38069364727SSebastian Andrzej Siewior 	struct format_field *fields        = evsel->tp_format->format.fields;
38169364727SSebastian Andrzej Siewior 	int ret;
38269364727SSebastian Andrzej Siewior 
38369364727SSebastian Andrzej Siewior 	ret = add_tracepoint_fields_values(cw, event_class, event,
38469364727SSebastian Andrzej Siewior 					   common_fields, sample);
38569364727SSebastian Andrzej Siewior 	if (!ret)
38669364727SSebastian Andrzej Siewior 		ret = add_tracepoint_fields_values(cw, event_class, event,
38769364727SSebastian Andrzej Siewior 						   fields, sample);
38869364727SSebastian Andrzej Siewior 
38969364727SSebastian Andrzej Siewior 	return ret;
39069364727SSebastian Andrzej Siewior }
39169364727SSebastian Andrzej Siewior 
3926122d57eSWang Nan static int
3936122d57eSWang Nan add_bpf_output_values(struct bt_ctf_event_class *event_class,
3946122d57eSWang Nan 		      struct bt_ctf_event *event,
3956122d57eSWang Nan 		      struct perf_sample *sample)
3966122d57eSWang Nan {
3976122d57eSWang Nan 	struct bt_ctf_field_type *len_type, *seq_type;
3986122d57eSWang Nan 	struct bt_ctf_field *len_field, *seq_field;
3996122d57eSWang Nan 	unsigned int raw_size = sample->raw_size;
4006122d57eSWang Nan 	unsigned int nr_elements = raw_size / sizeof(u32);
4016122d57eSWang Nan 	unsigned int i;
4026122d57eSWang Nan 	int ret;
4036122d57eSWang Nan 
4046122d57eSWang Nan 	if (nr_elements * sizeof(u32) != raw_size)
4056122d57eSWang Nan 		pr_warning("Incorrect raw_size (%u) in bpf output event, skip %lu bytes\n",
4066122d57eSWang Nan 			   raw_size, nr_elements * sizeof(u32) - raw_size);
4076122d57eSWang Nan 
4086122d57eSWang Nan 	len_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_len");
4096122d57eSWang Nan 	len_field = bt_ctf_field_create(len_type);
4106122d57eSWang Nan 	if (!len_field) {
4116122d57eSWang Nan 		pr_err("failed to create 'raw_len' for bpf output event\n");
4126122d57eSWang Nan 		ret = -1;
4136122d57eSWang Nan 		goto put_len_type;
4146122d57eSWang Nan 	}
4156122d57eSWang Nan 
4166122d57eSWang Nan 	ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements);
4176122d57eSWang Nan 	if (ret) {
4186122d57eSWang Nan 		pr_err("failed to set field value for raw_len\n");
4196122d57eSWang Nan 		goto put_len_field;
4206122d57eSWang Nan 	}
4216122d57eSWang Nan 	ret = bt_ctf_event_set_payload(event, "raw_len", len_field);
4226122d57eSWang Nan 	if (ret) {
4236122d57eSWang Nan 		pr_err("failed to set payload to raw_len\n");
4246122d57eSWang Nan 		goto put_len_field;
4256122d57eSWang Nan 	}
4266122d57eSWang Nan 
4276122d57eSWang Nan 	seq_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_data");
4286122d57eSWang Nan 	seq_field = bt_ctf_field_create(seq_type);
4296122d57eSWang Nan 	if (!seq_field) {
4306122d57eSWang Nan 		pr_err("failed to create 'raw_data' for bpf output event\n");
4316122d57eSWang Nan 		ret = -1;
4326122d57eSWang Nan 		goto put_seq_type;
4336122d57eSWang Nan 	}
4346122d57eSWang Nan 
4356122d57eSWang Nan 	ret = bt_ctf_field_sequence_set_length(seq_field, len_field);
4366122d57eSWang Nan 	if (ret) {
4376122d57eSWang Nan 		pr_err("failed to set length of 'raw_data'\n");
4386122d57eSWang Nan 		goto put_seq_field;
4396122d57eSWang Nan 	}
4406122d57eSWang Nan 
4416122d57eSWang Nan 	for (i = 0; i < nr_elements; i++) {
4426122d57eSWang Nan 		struct bt_ctf_field *elem_field =
4436122d57eSWang Nan 			bt_ctf_field_sequence_get_field(seq_field, i);
4446122d57eSWang Nan 
4456122d57eSWang Nan 		ret = bt_ctf_field_unsigned_integer_set_value(elem_field,
4466122d57eSWang Nan 				((u32 *)(sample->raw_data))[i]);
4476122d57eSWang Nan 
4486122d57eSWang Nan 		bt_ctf_field_put(elem_field);
4496122d57eSWang Nan 		if (ret) {
4506122d57eSWang Nan 			pr_err("failed to set raw_data[%d]\n", i);
4516122d57eSWang Nan 			goto put_seq_field;
4526122d57eSWang Nan 		}
4536122d57eSWang Nan 	}
4546122d57eSWang Nan 
4556122d57eSWang Nan 	ret = bt_ctf_event_set_payload(event, "raw_data", seq_field);
4566122d57eSWang Nan 	if (ret)
4576122d57eSWang Nan 		pr_err("failed to set payload for raw_data\n");
4586122d57eSWang Nan 
4596122d57eSWang Nan put_seq_field:
4606122d57eSWang Nan 	bt_ctf_field_put(seq_field);
4616122d57eSWang Nan put_seq_type:
4626122d57eSWang Nan 	bt_ctf_field_type_put(seq_type);
4636122d57eSWang Nan put_len_field:
4646122d57eSWang Nan 	bt_ctf_field_put(len_field);
4656122d57eSWang Nan put_len_type:
4666122d57eSWang Nan 	bt_ctf_field_type_put(len_type);
4676122d57eSWang Nan 	return ret;
4686122d57eSWang Nan }
4696122d57eSWang Nan 
470edbe9817SJiri Olsa static int add_generic_values(struct ctf_writer *cw,
471edbe9817SJiri Olsa 			      struct bt_ctf_event *event,
472edbe9817SJiri Olsa 			      struct perf_evsel *evsel,
473edbe9817SJiri Olsa 			      struct perf_sample *sample)
474edbe9817SJiri Olsa {
475edbe9817SJiri Olsa 	u64 type = evsel->attr.sample_type;
476edbe9817SJiri Olsa 	int ret;
477edbe9817SJiri Olsa 
478edbe9817SJiri Olsa 	/*
479edbe9817SJiri Olsa 	 * missing:
480edbe9817SJiri Olsa 	 *   PERF_SAMPLE_TIME         - not needed as we have it in
481edbe9817SJiri Olsa 	 *                              ctf event header
482edbe9817SJiri Olsa 	 *   PERF_SAMPLE_READ         - TODO
483edbe9817SJiri Olsa 	 *   PERF_SAMPLE_CALLCHAIN    - TODO
484edbe9817SJiri Olsa 	 *   PERF_SAMPLE_RAW          - tracepoint fields are handled separately
485edbe9817SJiri Olsa 	 *   PERF_SAMPLE_BRANCH_STACK - TODO
486edbe9817SJiri Olsa 	 *   PERF_SAMPLE_REGS_USER    - TODO
487edbe9817SJiri Olsa 	 *   PERF_SAMPLE_STACK_USER   - TODO
488edbe9817SJiri Olsa 	 */
489edbe9817SJiri Olsa 
490edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_IP) {
49154cf776aSSebastian Andrzej Siewior 		ret = value_set_u64_hex(cw, event, "perf_ip", sample->ip);
492edbe9817SJiri Olsa 		if (ret)
493edbe9817SJiri Olsa 			return -1;
494edbe9817SJiri Olsa 	}
495edbe9817SJiri Olsa 
496edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_TID) {
49754cf776aSSebastian Andrzej Siewior 		ret = value_set_s32(cw, event, "perf_tid", sample->tid);
498edbe9817SJiri Olsa 		if (ret)
499edbe9817SJiri Olsa 			return -1;
500edbe9817SJiri Olsa 
50154cf776aSSebastian Andrzej Siewior 		ret = value_set_s32(cw, event, "perf_pid", sample->pid);
502edbe9817SJiri Olsa 		if (ret)
503edbe9817SJiri Olsa 			return -1;
504edbe9817SJiri Olsa 	}
505edbe9817SJiri Olsa 
506edbe9817SJiri Olsa 	if ((type & PERF_SAMPLE_ID) ||
507edbe9817SJiri Olsa 	    (type & PERF_SAMPLE_IDENTIFIER)) {
50854cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_id", sample->id);
509edbe9817SJiri Olsa 		if (ret)
510edbe9817SJiri Olsa 			return -1;
511edbe9817SJiri Olsa 	}
512edbe9817SJiri Olsa 
513edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_STREAM_ID) {
51454cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_stream_id", sample->stream_id);
515edbe9817SJiri Olsa 		if (ret)
516edbe9817SJiri Olsa 			return -1;
517edbe9817SJiri Olsa 	}
518edbe9817SJiri Olsa 
519edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_PERIOD) {
52054cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_period", sample->period);
521edbe9817SJiri Olsa 		if (ret)
522edbe9817SJiri Olsa 			return -1;
523edbe9817SJiri Olsa 	}
524edbe9817SJiri Olsa 
525edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_WEIGHT) {
52654cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_weight", sample->weight);
527edbe9817SJiri Olsa 		if (ret)
528edbe9817SJiri Olsa 			return -1;
529edbe9817SJiri Olsa 	}
530edbe9817SJiri Olsa 
531edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_DATA_SRC) {
53254cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_data_src",
53354cf776aSSebastian Andrzej Siewior 				sample->data_src);
534edbe9817SJiri Olsa 		if (ret)
535edbe9817SJiri Olsa 			return -1;
536edbe9817SJiri Olsa 	}
537edbe9817SJiri Olsa 
538edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_TRANSACTION) {
53954cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_transaction",
54054cf776aSSebastian Andrzej Siewior 				sample->transaction);
541edbe9817SJiri Olsa 		if (ret)
542edbe9817SJiri Olsa 			return -1;
543edbe9817SJiri Olsa 	}
544edbe9817SJiri Olsa 
545edbe9817SJiri Olsa 	return 0;
546edbe9817SJiri Olsa }
547edbe9817SJiri Olsa 
54890e129ffSSebastian Andrzej Siewior static int ctf_stream__flush(struct ctf_stream *cs)
54990e129ffSSebastian Andrzej Siewior {
55090e129ffSSebastian Andrzej Siewior 	int err = 0;
55190e129ffSSebastian Andrzej Siewior 
55290e129ffSSebastian Andrzej Siewior 	if (cs) {
55390e129ffSSebastian Andrzej Siewior 		err = bt_ctf_stream_flush(cs->stream);
55490e129ffSSebastian Andrzej Siewior 		if (err)
55590e129ffSSebastian Andrzej Siewior 			pr_err("CTF stream %d flush failed\n", cs->cpu);
55690e129ffSSebastian Andrzej Siewior 
55789e5fa88SJiri Olsa 		pr("Flush stream for cpu %d (%u samples)\n",
55889e5fa88SJiri Olsa 		   cs->cpu, cs->count);
55989e5fa88SJiri Olsa 
56089e5fa88SJiri Olsa 		cs->count = 0;
56190e129ffSSebastian Andrzej Siewior 	}
56290e129ffSSebastian Andrzej Siewior 
56390e129ffSSebastian Andrzej Siewior 	return err;
56490e129ffSSebastian Andrzej Siewior }
56590e129ffSSebastian Andrzej Siewior 
56690e129ffSSebastian Andrzej Siewior static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu)
56790e129ffSSebastian Andrzej Siewior {
56890e129ffSSebastian Andrzej Siewior 	struct ctf_stream *cs;
56990e129ffSSebastian Andrzej Siewior 	struct bt_ctf_field *pkt_ctx   = NULL;
57090e129ffSSebastian Andrzej Siewior 	struct bt_ctf_field *cpu_field = NULL;
57190e129ffSSebastian Andrzej Siewior 	struct bt_ctf_stream *stream   = NULL;
57290e129ffSSebastian Andrzej Siewior 	int ret;
57390e129ffSSebastian Andrzej Siewior 
57490e129ffSSebastian Andrzej Siewior 	cs = zalloc(sizeof(*cs));
57590e129ffSSebastian Andrzej Siewior 	if (!cs) {
57690e129ffSSebastian Andrzej Siewior 		pr_err("Failed to allocate ctf stream\n");
57790e129ffSSebastian Andrzej Siewior 		return NULL;
57890e129ffSSebastian Andrzej Siewior 	}
57990e129ffSSebastian Andrzej Siewior 
58090e129ffSSebastian Andrzej Siewior 	stream = bt_ctf_writer_create_stream(cw->writer, cw->stream_class);
58190e129ffSSebastian Andrzej Siewior 	if (!stream) {
58290e129ffSSebastian Andrzej Siewior 		pr_err("Failed to create CTF stream\n");
58390e129ffSSebastian Andrzej Siewior 		goto out;
58490e129ffSSebastian Andrzej Siewior 	}
58590e129ffSSebastian Andrzej Siewior 
58690e129ffSSebastian Andrzej Siewior 	pkt_ctx = bt_ctf_stream_get_packet_context(stream);
58790e129ffSSebastian Andrzej Siewior 	if (!pkt_ctx) {
58890e129ffSSebastian Andrzej Siewior 		pr_err("Failed to obtain packet context\n");
58990e129ffSSebastian Andrzej Siewior 		goto out;
59090e129ffSSebastian Andrzej Siewior 	}
59190e129ffSSebastian Andrzej Siewior 
59290e129ffSSebastian Andrzej Siewior 	cpu_field = bt_ctf_field_structure_get_field(pkt_ctx, "cpu_id");
59390e129ffSSebastian Andrzej Siewior 	bt_ctf_field_put(pkt_ctx);
59490e129ffSSebastian Andrzej Siewior 	if (!cpu_field) {
59590e129ffSSebastian Andrzej Siewior 		pr_err("Failed to obtain cpu field\n");
59690e129ffSSebastian Andrzej Siewior 		goto out;
59790e129ffSSebastian Andrzej Siewior 	}
59890e129ffSSebastian Andrzej Siewior 
59990e129ffSSebastian Andrzej Siewior 	ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu);
60090e129ffSSebastian Andrzej Siewior 	if (ret) {
60190e129ffSSebastian Andrzej Siewior 		pr_err("Failed to update CPU number\n");
60290e129ffSSebastian Andrzej Siewior 		goto out;
60390e129ffSSebastian Andrzej Siewior 	}
60490e129ffSSebastian Andrzej Siewior 
60590e129ffSSebastian Andrzej Siewior 	bt_ctf_field_put(cpu_field);
60690e129ffSSebastian Andrzej Siewior 
60790e129ffSSebastian Andrzej Siewior 	cs->cpu    = cpu;
60890e129ffSSebastian Andrzej Siewior 	cs->stream = stream;
60990e129ffSSebastian Andrzej Siewior 	return cs;
61090e129ffSSebastian Andrzej Siewior 
61190e129ffSSebastian Andrzej Siewior out:
61290e129ffSSebastian Andrzej Siewior 	if (cpu_field)
61390e129ffSSebastian Andrzej Siewior 		bt_ctf_field_put(cpu_field);
61490e129ffSSebastian Andrzej Siewior 	if (stream)
61590e129ffSSebastian Andrzej Siewior 		bt_ctf_stream_put(stream);
61690e129ffSSebastian Andrzej Siewior 
61790e129ffSSebastian Andrzej Siewior 	free(cs);
61890e129ffSSebastian Andrzej Siewior 	return NULL;
61990e129ffSSebastian Andrzej Siewior }
62090e129ffSSebastian Andrzej Siewior 
62190e129ffSSebastian Andrzej Siewior static void ctf_stream__delete(struct ctf_stream *cs)
62290e129ffSSebastian Andrzej Siewior {
62390e129ffSSebastian Andrzej Siewior 	if (cs) {
62490e129ffSSebastian Andrzej Siewior 		bt_ctf_stream_put(cs->stream);
62590e129ffSSebastian Andrzej Siewior 		free(cs);
62690e129ffSSebastian Andrzej Siewior 	}
62790e129ffSSebastian Andrzej Siewior }
62890e129ffSSebastian Andrzej Siewior 
62990e129ffSSebastian Andrzej Siewior static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu)
63090e129ffSSebastian Andrzej Siewior {
63190e129ffSSebastian Andrzej Siewior 	struct ctf_stream *cs = cw->stream[cpu];
63290e129ffSSebastian Andrzej Siewior 
63390e129ffSSebastian Andrzej Siewior 	if (!cs) {
63490e129ffSSebastian Andrzej Siewior 		cs = ctf_stream__create(cw, cpu);
63590e129ffSSebastian Andrzej Siewior 		cw->stream[cpu] = cs;
63690e129ffSSebastian Andrzej Siewior 	}
63790e129ffSSebastian Andrzej Siewior 
63890e129ffSSebastian Andrzej Siewior 	return cs;
63990e129ffSSebastian Andrzej Siewior }
64090e129ffSSebastian Andrzej Siewior 
64190e129ffSSebastian Andrzej Siewior static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample,
64290e129ffSSebastian Andrzej Siewior 			  struct perf_evsel *evsel)
64390e129ffSSebastian Andrzej Siewior {
64490e129ffSSebastian Andrzej Siewior 	int cpu = 0;
64590e129ffSSebastian Andrzej Siewior 
64690e129ffSSebastian Andrzej Siewior 	if (evsel->attr.sample_type & PERF_SAMPLE_CPU)
64790e129ffSSebastian Andrzej Siewior 		cpu = sample->cpu;
64890e129ffSSebastian Andrzej Siewior 
64990e129ffSSebastian Andrzej Siewior 	if (cpu > cw->stream_cnt) {
65090e129ffSSebastian Andrzej Siewior 		pr_err("Event was recorded for CPU %d, limit is at %d.\n",
65190e129ffSSebastian Andrzej Siewior 			cpu, cw->stream_cnt);
65290e129ffSSebastian Andrzej Siewior 		cpu = 0;
65390e129ffSSebastian Andrzej Siewior 	}
65490e129ffSSebastian Andrzej Siewior 
65590e129ffSSebastian Andrzej Siewior 	return cpu;
65690e129ffSSebastian Andrzej Siewior }
65790e129ffSSebastian Andrzej Siewior 
65889e5fa88SJiri Olsa #define STREAM_FLUSH_COUNT 100000
65989e5fa88SJiri Olsa 
66089e5fa88SJiri Olsa /*
66189e5fa88SJiri Olsa  * Currently we have no other way to determine the
66289e5fa88SJiri Olsa  * time for the stream flush other than keep track
66389e5fa88SJiri Olsa  * of the number of events and check it against
66489e5fa88SJiri Olsa  * threshold.
66589e5fa88SJiri Olsa  */
66689e5fa88SJiri Olsa static bool is_flush_needed(struct ctf_stream *cs)
66789e5fa88SJiri Olsa {
66889e5fa88SJiri Olsa 	return cs->count >= STREAM_FLUSH_COUNT;
66989e5fa88SJiri Olsa }
67089e5fa88SJiri Olsa 
671edbe9817SJiri Olsa static int process_sample_event(struct perf_tool *tool,
672b8f8eb84SArnaldo Carvalho de Melo 				union perf_event *_event,
673edbe9817SJiri Olsa 				struct perf_sample *sample,
674edbe9817SJiri Olsa 				struct perf_evsel *evsel,
675edbe9817SJiri Olsa 				struct machine *machine __maybe_unused)
676edbe9817SJiri Olsa {
677edbe9817SJiri Olsa 	struct convert *c = container_of(tool, struct convert, tool);
678edbe9817SJiri Olsa 	struct evsel_priv *priv = evsel->priv;
679edbe9817SJiri Olsa 	struct ctf_writer *cw = &c->writer;
68090e129ffSSebastian Andrzej Siewior 	struct ctf_stream *cs;
681edbe9817SJiri Olsa 	struct bt_ctf_event_class *event_class;
682edbe9817SJiri Olsa 	struct bt_ctf_event *event;
683edbe9817SJiri Olsa 	int ret;
684edbe9817SJiri Olsa 
685edbe9817SJiri Olsa 	if (WARN_ONCE(!priv, "Failed to setup all events.\n"))
686edbe9817SJiri Olsa 		return 0;
687edbe9817SJiri Olsa 
688edbe9817SJiri Olsa 	event_class = priv->event_class;
689edbe9817SJiri Olsa 
690edbe9817SJiri Olsa 	/* update stats */
691edbe9817SJiri Olsa 	c->events_count++;
692edbe9817SJiri Olsa 	c->events_size += _event->header.size;
693edbe9817SJiri Olsa 
694edbe9817SJiri Olsa 	pr_time2(sample->time, "sample %" PRIu64 "\n", c->events_count);
695edbe9817SJiri Olsa 
696edbe9817SJiri Olsa 	event = bt_ctf_event_create(event_class);
697edbe9817SJiri Olsa 	if (!event) {
698edbe9817SJiri Olsa 		pr_err("Failed to create an CTF event\n");
699edbe9817SJiri Olsa 		return -1;
700edbe9817SJiri Olsa 	}
701edbe9817SJiri Olsa 
702edbe9817SJiri Olsa 	bt_ctf_clock_set_time(cw->clock, sample->time);
703edbe9817SJiri Olsa 
704edbe9817SJiri Olsa 	ret = add_generic_values(cw, event, evsel, sample);
705edbe9817SJiri Olsa 	if (ret)
706edbe9817SJiri Olsa 		return -1;
707edbe9817SJiri Olsa 
70869364727SSebastian Andrzej Siewior 	if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
70969364727SSebastian Andrzej Siewior 		ret = add_tracepoint_values(cw, event_class, event,
71069364727SSebastian Andrzej Siewior 					    evsel, sample);
71169364727SSebastian Andrzej Siewior 		if (ret)
71269364727SSebastian Andrzej Siewior 			return -1;
71369364727SSebastian Andrzej Siewior 	}
71469364727SSebastian Andrzej Siewior 
7156122d57eSWang Nan 	if (perf_evsel__is_bpf_output(evsel)) {
7166122d57eSWang Nan 		ret = add_bpf_output_values(event_class, event, sample);
7176122d57eSWang Nan 		if (ret)
7186122d57eSWang Nan 			return -1;
7196122d57eSWang Nan 	}
7206122d57eSWang Nan 
72190e129ffSSebastian Andrzej Siewior 	cs = ctf_stream(cw, get_sample_cpu(cw, sample, evsel));
72289e5fa88SJiri Olsa 	if (cs) {
72389e5fa88SJiri Olsa 		if (is_flush_needed(cs))
72489e5fa88SJiri Olsa 			ctf_stream__flush(cs);
72589e5fa88SJiri Olsa 
72689e5fa88SJiri Olsa 		cs->count++;
72790e129ffSSebastian Andrzej Siewior 		bt_ctf_stream_append_event(cs->stream, event);
72889e5fa88SJiri Olsa 	}
72990e129ffSSebastian Andrzej Siewior 
730edbe9817SJiri Olsa 	bt_ctf_event_put(event);
73190e129ffSSebastian Andrzej Siewior 	return cs ? 0 : -1;
732edbe9817SJiri Olsa }
733edbe9817SJiri Olsa 
734e0a7cce5SWang Nan /* If dup < 0, add a prefix. Else, add _dupl_X suffix. */
735e0a7cce5SWang Nan static char *change_name(char *name, char *orig_name, int dup)
736e0a7cce5SWang Nan {
737e0a7cce5SWang Nan 	char *new_name = NULL;
738e0a7cce5SWang Nan 	size_t len;
739e0a7cce5SWang Nan 
740e0a7cce5SWang Nan 	if (!name)
741e0a7cce5SWang Nan 		name = orig_name;
742e0a7cce5SWang Nan 
743e0a7cce5SWang Nan 	if (dup >= 10)
744e0a7cce5SWang Nan 		goto out;
745e0a7cce5SWang Nan 	/*
746e0a7cce5SWang Nan 	 * Add '_' prefix to potential keywork.  According to
747e0a7cce5SWang Nan 	 * Mathieu Desnoyers (https://lkml.org/lkml/2015/1/23/652),
748e0a7cce5SWang Nan 	 * futher CTF spec updating may require us to use '$'.
749e0a7cce5SWang Nan 	 */
750e0a7cce5SWang Nan 	if (dup < 0)
751e0a7cce5SWang Nan 		len = strlen(name) + sizeof("_");
752e0a7cce5SWang Nan 	else
753e0a7cce5SWang Nan 		len = strlen(orig_name) + sizeof("_dupl_X");
754e0a7cce5SWang Nan 
755e0a7cce5SWang Nan 	new_name = malloc(len);
756e0a7cce5SWang Nan 	if (!new_name)
757e0a7cce5SWang Nan 		goto out;
758e0a7cce5SWang Nan 
759e0a7cce5SWang Nan 	if (dup < 0)
760e0a7cce5SWang Nan 		snprintf(new_name, len, "_%s", name);
761e0a7cce5SWang Nan 	else
762e0a7cce5SWang Nan 		snprintf(new_name, len, "%s_dupl_%d", orig_name, dup);
763e0a7cce5SWang Nan 
764e0a7cce5SWang Nan out:
765e0a7cce5SWang Nan 	if (name != orig_name)
766e0a7cce5SWang Nan 		free(name);
767e0a7cce5SWang Nan 	return new_name;
768e0a7cce5SWang Nan }
769e0a7cce5SWang Nan 
770e0a7cce5SWang Nan static int event_class_add_field(struct bt_ctf_event_class *event_class,
771e0a7cce5SWang Nan 		struct bt_ctf_field_type *type,
772e0a7cce5SWang Nan 		struct format_field *field)
773e0a7cce5SWang Nan {
774e0a7cce5SWang Nan 	struct bt_ctf_field_type *t = NULL;
775e0a7cce5SWang Nan 	char *name;
776e0a7cce5SWang Nan 	int dup = 1;
777e0a7cce5SWang Nan 	int ret;
778e0a7cce5SWang Nan 
779e0a7cce5SWang Nan 	/* alias was already assigned */
780e0a7cce5SWang Nan 	if (field->alias != field->name)
781e0a7cce5SWang Nan 		return bt_ctf_event_class_add_field(event_class, type,
782e0a7cce5SWang Nan 				(char *)field->alias);
783e0a7cce5SWang Nan 
784e0a7cce5SWang Nan 	name = field->name;
785e0a7cce5SWang Nan 
786e0a7cce5SWang Nan 	/* If 'name' is a keywork, add prefix. */
787e0a7cce5SWang Nan 	if (bt_ctf_validate_identifier(name))
788e0a7cce5SWang Nan 		name = change_name(name, field->name, -1);
789e0a7cce5SWang Nan 
790e0a7cce5SWang Nan 	if (!name) {
791e0a7cce5SWang Nan 		pr_err("Failed to fix invalid identifier.");
792e0a7cce5SWang Nan 		return -1;
793e0a7cce5SWang Nan 	}
794e0a7cce5SWang Nan 	while ((t = bt_ctf_event_class_get_field_by_name(event_class, name))) {
795e0a7cce5SWang Nan 		bt_ctf_field_type_put(t);
796e0a7cce5SWang Nan 		name = change_name(name, field->name, dup++);
797e0a7cce5SWang Nan 		if (!name) {
798e0a7cce5SWang Nan 			pr_err("Failed to create dup name for '%s'\n", field->name);
799e0a7cce5SWang Nan 			return -1;
800e0a7cce5SWang Nan 		}
801e0a7cce5SWang Nan 	}
802e0a7cce5SWang Nan 
803e0a7cce5SWang Nan 	ret = bt_ctf_event_class_add_field(event_class, type, name);
804e0a7cce5SWang Nan 	if (!ret)
805e0a7cce5SWang Nan 		field->alias = name;
806e0a7cce5SWang Nan 
807e0a7cce5SWang Nan 	return ret;
808e0a7cce5SWang Nan }
809e0a7cce5SWang Nan 
81069364727SSebastian Andrzej Siewior static int add_tracepoint_fields_types(struct ctf_writer *cw,
81169364727SSebastian Andrzej Siewior 				       struct format_field *fields,
81269364727SSebastian Andrzej Siewior 				       struct bt_ctf_event_class *event_class)
81369364727SSebastian Andrzej Siewior {
81469364727SSebastian Andrzej Siewior 	struct format_field *field;
81569364727SSebastian Andrzej Siewior 	int ret;
81669364727SSebastian Andrzej Siewior 
81769364727SSebastian Andrzej Siewior 	for (field = fields; field; field = field->next) {
81869364727SSebastian Andrzej Siewior 		struct bt_ctf_field_type *type;
81969364727SSebastian Andrzej Siewior 		unsigned long flags = field->flags;
82069364727SSebastian Andrzej Siewior 
82169364727SSebastian Andrzej Siewior 		pr2("  field '%s'\n", field->name);
82269364727SSebastian Andrzej Siewior 
82369364727SSebastian Andrzej Siewior 		type = get_tracepoint_field_type(cw, field);
82469364727SSebastian Andrzej Siewior 		if (!type)
82569364727SSebastian Andrzej Siewior 			return -1;
82669364727SSebastian Andrzej Siewior 
82769364727SSebastian Andrzej Siewior 		/*
82869364727SSebastian Andrzej Siewior 		 * A string is an array of chars. For this we use the string
82969364727SSebastian Andrzej Siewior 		 * type and don't care that it is an array. What we don't
83069364727SSebastian Andrzej Siewior 		 * support is an array of strings.
83169364727SSebastian Andrzej Siewior 		 */
83269364727SSebastian Andrzej Siewior 		if (flags & FIELD_IS_STRING)
83369364727SSebastian Andrzej Siewior 			flags &= ~FIELD_IS_ARRAY;
83469364727SSebastian Andrzej Siewior 
83569364727SSebastian Andrzej Siewior 		if (flags & FIELD_IS_ARRAY)
83669364727SSebastian Andrzej Siewior 			type = bt_ctf_field_type_array_create(type, field->arraylen);
83769364727SSebastian Andrzej Siewior 
838e0a7cce5SWang Nan 		ret = event_class_add_field(event_class, type, field);
83969364727SSebastian Andrzej Siewior 
84069364727SSebastian Andrzej Siewior 		if (flags & FIELD_IS_ARRAY)
84169364727SSebastian Andrzej Siewior 			bt_ctf_field_type_put(type);
84269364727SSebastian Andrzej Siewior 
84369364727SSebastian Andrzej Siewior 		if (ret) {
844e0a7cce5SWang Nan 			pr_err("Failed to add field '%s': %d\n",
845e0a7cce5SWang Nan 					field->name, ret);
84669364727SSebastian Andrzej Siewior 			return -1;
84769364727SSebastian Andrzej Siewior 		}
84869364727SSebastian Andrzej Siewior 	}
84969364727SSebastian Andrzej Siewior 
85069364727SSebastian Andrzej Siewior 	return 0;
85169364727SSebastian Andrzej Siewior }
85269364727SSebastian Andrzej Siewior 
85369364727SSebastian Andrzej Siewior static int add_tracepoint_types(struct ctf_writer *cw,
85469364727SSebastian Andrzej Siewior 				struct perf_evsel *evsel,
85569364727SSebastian Andrzej Siewior 				struct bt_ctf_event_class *class)
85669364727SSebastian Andrzej Siewior {
85769364727SSebastian Andrzej Siewior 	struct format_field *common_fields = evsel->tp_format->format.common_fields;
85869364727SSebastian Andrzej Siewior 	struct format_field *fields        = evsel->tp_format->format.fields;
85969364727SSebastian Andrzej Siewior 	int ret;
86069364727SSebastian Andrzej Siewior 
86169364727SSebastian Andrzej Siewior 	ret = add_tracepoint_fields_types(cw, common_fields, class);
86269364727SSebastian Andrzej Siewior 	if (!ret)
86369364727SSebastian Andrzej Siewior 		ret = add_tracepoint_fields_types(cw, fields, class);
86469364727SSebastian Andrzej Siewior 
86569364727SSebastian Andrzej Siewior 	return ret;
86669364727SSebastian Andrzej Siewior }
86769364727SSebastian Andrzej Siewior 
8686122d57eSWang Nan static int add_bpf_output_types(struct ctf_writer *cw,
8696122d57eSWang Nan 				struct bt_ctf_event_class *class)
8706122d57eSWang Nan {
8716122d57eSWang Nan 	struct bt_ctf_field_type *len_type = cw->data.u32;
8726122d57eSWang Nan 	struct bt_ctf_field_type *seq_base_type = cw->data.u32_hex;
8736122d57eSWang Nan 	struct bt_ctf_field_type *seq_type;
8746122d57eSWang Nan 	int ret;
8756122d57eSWang Nan 
8766122d57eSWang Nan 	ret = bt_ctf_event_class_add_field(class, len_type, "raw_len");
8776122d57eSWang Nan 	if (ret)
8786122d57eSWang Nan 		return ret;
8796122d57eSWang Nan 
8806122d57eSWang Nan 	seq_type = bt_ctf_field_type_sequence_create(seq_base_type, "raw_len");
8816122d57eSWang Nan 	if (!seq_type)
8826122d57eSWang Nan 		return -1;
8836122d57eSWang Nan 
8846122d57eSWang Nan 	return bt_ctf_event_class_add_field(class, seq_type, "raw_data");
8856122d57eSWang Nan }
8866122d57eSWang Nan 
887edbe9817SJiri Olsa static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
888edbe9817SJiri Olsa 			     struct bt_ctf_event_class *event_class)
889edbe9817SJiri Olsa {
890edbe9817SJiri Olsa 	u64 type = evsel->attr.sample_type;
891edbe9817SJiri Olsa 
892edbe9817SJiri Olsa 	/*
893edbe9817SJiri Olsa 	 * missing:
894edbe9817SJiri Olsa 	 *   PERF_SAMPLE_TIME         - not needed as we have it in
895edbe9817SJiri Olsa 	 *                              ctf event header
896edbe9817SJiri Olsa 	 *   PERF_SAMPLE_READ         - TODO
897edbe9817SJiri Olsa 	 *   PERF_SAMPLE_CALLCHAIN    - TODO
8986122d57eSWang Nan 	 *   PERF_SAMPLE_RAW          - tracepoint fields and BPF output
8996122d57eSWang Nan 	 *                              are handled separately
900edbe9817SJiri Olsa 	 *   PERF_SAMPLE_BRANCH_STACK - TODO
901edbe9817SJiri Olsa 	 *   PERF_SAMPLE_REGS_USER    - TODO
902edbe9817SJiri Olsa 	 *   PERF_SAMPLE_STACK_USER   - TODO
903edbe9817SJiri Olsa 	 */
904edbe9817SJiri Olsa 
905edbe9817SJiri Olsa #define ADD_FIELD(cl, t, n)						\
906edbe9817SJiri Olsa 	do {								\
907edbe9817SJiri Olsa 		pr2("  field '%s'\n", n);				\
908edbe9817SJiri Olsa 		if (bt_ctf_event_class_add_field(cl, t, n)) {		\
909e0a7cce5SWang Nan 			pr_err("Failed to add field '%s';\n", n);	\
910edbe9817SJiri Olsa 			return -1;					\
911edbe9817SJiri Olsa 		}							\
912edbe9817SJiri Olsa 	} while (0)
913edbe9817SJiri Olsa 
914edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_IP)
91554cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64_hex, "perf_ip");
916edbe9817SJiri Olsa 
917edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_TID) {
91854cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.s32, "perf_tid");
91954cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.s32, "perf_pid");
920edbe9817SJiri Olsa 	}
921edbe9817SJiri Olsa 
922edbe9817SJiri Olsa 	if ((type & PERF_SAMPLE_ID) ||
923edbe9817SJiri Olsa 	    (type & PERF_SAMPLE_IDENTIFIER))
92454cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_id");
925edbe9817SJiri Olsa 
926edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_STREAM_ID)
92754cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_stream_id");
928edbe9817SJiri Olsa 
929edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_PERIOD)
93054cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_period");
931edbe9817SJiri Olsa 
932edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_WEIGHT)
93354cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_weight");
934edbe9817SJiri Olsa 
935edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_DATA_SRC)
93654cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_data_src");
937edbe9817SJiri Olsa 
938edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_TRANSACTION)
93954cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_transaction");
940edbe9817SJiri Olsa 
941edbe9817SJiri Olsa #undef ADD_FIELD
942edbe9817SJiri Olsa 	return 0;
943edbe9817SJiri Olsa }
944edbe9817SJiri Olsa 
945edbe9817SJiri Olsa static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
946edbe9817SJiri Olsa {
947edbe9817SJiri Olsa 	struct bt_ctf_event_class *event_class;
948edbe9817SJiri Olsa 	struct evsel_priv *priv;
949edbe9817SJiri Olsa 	const char *name = perf_evsel__name(evsel);
950edbe9817SJiri Olsa 	int ret;
951edbe9817SJiri Olsa 
952edbe9817SJiri Olsa 	pr("Adding event '%s' (type %d)\n", name, evsel->attr.type);
953edbe9817SJiri Olsa 
954edbe9817SJiri Olsa 	event_class = bt_ctf_event_class_create(name);
955edbe9817SJiri Olsa 	if (!event_class)
956edbe9817SJiri Olsa 		return -1;
957edbe9817SJiri Olsa 
958edbe9817SJiri Olsa 	ret = add_generic_types(cw, evsel, event_class);
959edbe9817SJiri Olsa 	if (ret)
960edbe9817SJiri Olsa 		goto err;
961edbe9817SJiri Olsa 
96269364727SSebastian Andrzej Siewior 	if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
96369364727SSebastian Andrzej Siewior 		ret = add_tracepoint_types(cw, evsel, event_class);
96469364727SSebastian Andrzej Siewior 		if (ret)
96569364727SSebastian Andrzej Siewior 			goto err;
96669364727SSebastian Andrzej Siewior 	}
96769364727SSebastian Andrzej Siewior 
9686122d57eSWang Nan 	if (perf_evsel__is_bpf_output(evsel)) {
9696122d57eSWang Nan 		ret = add_bpf_output_types(cw, event_class);
9706122d57eSWang Nan 		if (ret)
9716122d57eSWang Nan 			goto err;
9726122d57eSWang Nan 	}
9736122d57eSWang Nan 
974edbe9817SJiri Olsa 	ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);
975edbe9817SJiri Olsa 	if (ret) {
976edbe9817SJiri Olsa 		pr("Failed to add event class into stream.\n");
977edbe9817SJiri Olsa 		goto err;
978edbe9817SJiri Olsa 	}
979edbe9817SJiri Olsa 
980edbe9817SJiri Olsa 	priv = malloc(sizeof(*priv));
981edbe9817SJiri Olsa 	if (!priv)
982edbe9817SJiri Olsa 		goto err;
983edbe9817SJiri Olsa 
984edbe9817SJiri Olsa 	priv->event_class = event_class;
985edbe9817SJiri Olsa 	evsel->priv       = priv;
986edbe9817SJiri Olsa 	return 0;
987edbe9817SJiri Olsa 
988edbe9817SJiri Olsa err:
989edbe9817SJiri Olsa 	bt_ctf_event_class_put(event_class);
990edbe9817SJiri Olsa 	pr_err("Failed to add event '%s'.\n", name);
991edbe9817SJiri Olsa 	return -1;
992edbe9817SJiri Olsa }
993edbe9817SJiri Olsa 
994edbe9817SJiri Olsa static int setup_events(struct ctf_writer *cw, struct perf_session *session)
995edbe9817SJiri Olsa {
996edbe9817SJiri Olsa 	struct perf_evlist *evlist = session->evlist;
997edbe9817SJiri Olsa 	struct perf_evsel *evsel;
998edbe9817SJiri Olsa 	int ret;
999edbe9817SJiri Olsa 
1000edbe9817SJiri Olsa 	evlist__for_each(evlist, evsel) {
1001edbe9817SJiri Olsa 		ret = add_event(cw, evsel);
1002edbe9817SJiri Olsa 		if (ret)
1003edbe9817SJiri Olsa 			return ret;
1004edbe9817SJiri Olsa 	}
1005edbe9817SJiri Olsa 	return 0;
1006edbe9817SJiri Olsa }
1007edbe9817SJiri Olsa 
10085141d735SWang Nan static void cleanup_events(struct perf_session *session)
10095141d735SWang Nan {
10105141d735SWang Nan 	struct perf_evlist *evlist = session->evlist;
10115141d735SWang Nan 	struct perf_evsel *evsel;
10125141d735SWang Nan 
10135141d735SWang Nan 	evlist__for_each(evlist, evsel) {
10145141d735SWang Nan 		struct evsel_priv *priv;
10155141d735SWang Nan 
10165141d735SWang Nan 		priv = evsel->priv;
10175141d735SWang Nan 		bt_ctf_event_class_put(priv->event_class);
10185141d735SWang Nan 		zfree(&evsel->priv);
10195141d735SWang Nan 	}
10205141d735SWang Nan 
10215141d735SWang Nan 	perf_evlist__delete(evlist);
10225141d735SWang Nan 	session->evlist = NULL;
10235141d735SWang Nan }
10245141d735SWang Nan 
102590e129ffSSebastian Andrzej Siewior static int setup_streams(struct ctf_writer *cw, struct perf_session *session)
102690e129ffSSebastian Andrzej Siewior {
102790e129ffSSebastian Andrzej Siewior 	struct ctf_stream **stream;
102890e129ffSSebastian Andrzej Siewior 	struct perf_header *ph = &session->header;
102990e129ffSSebastian Andrzej Siewior 	int ncpus;
103090e129ffSSebastian Andrzej Siewior 
103190e129ffSSebastian Andrzej Siewior 	/*
103290e129ffSSebastian Andrzej Siewior 	 * Try to get the number of cpus used in the data file,
103390e129ffSSebastian Andrzej Siewior 	 * if not present fallback to the MAX_CPUS.
103490e129ffSSebastian Andrzej Siewior 	 */
103590e129ffSSebastian Andrzej Siewior 	ncpus = ph->env.nr_cpus_avail ?: MAX_CPUS;
103690e129ffSSebastian Andrzej Siewior 
103790e129ffSSebastian Andrzej Siewior 	stream = zalloc(sizeof(*stream) * ncpus);
103890e129ffSSebastian Andrzej Siewior 	if (!stream) {
103990e129ffSSebastian Andrzej Siewior 		pr_err("Failed to allocate streams.\n");
104090e129ffSSebastian Andrzej Siewior 		return -ENOMEM;
104190e129ffSSebastian Andrzej Siewior 	}
104290e129ffSSebastian Andrzej Siewior 
104390e129ffSSebastian Andrzej Siewior 	cw->stream     = stream;
104490e129ffSSebastian Andrzej Siewior 	cw->stream_cnt = ncpus;
104590e129ffSSebastian Andrzej Siewior 	return 0;
104690e129ffSSebastian Andrzej Siewior }
104790e129ffSSebastian Andrzej Siewior 
104890e129ffSSebastian Andrzej Siewior static void free_streams(struct ctf_writer *cw)
104990e129ffSSebastian Andrzej Siewior {
105090e129ffSSebastian Andrzej Siewior 	int cpu;
105190e129ffSSebastian Andrzej Siewior 
105290e129ffSSebastian Andrzej Siewior 	for (cpu = 0; cpu < cw->stream_cnt; cpu++)
105390e129ffSSebastian Andrzej Siewior 		ctf_stream__delete(cw->stream[cpu]);
105490e129ffSSebastian Andrzej Siewior 
105590e129ffSSebastian Andrzej Siewior 	free(cw->stream);
105690e129ffSSebastian Andrzej Siewior }
105790e129ffSSebastian Andrzej Siewior 
1058edbe9817SJiri Olsa static int ctf_writer__setup_env(struct ctf_writer *cw,
1059edbe9817SJiri Olsa 				 struct perf_session *session)
1060edbe9817SJiri Olsa {
1061edbe9817SJiri Olsa 	struct perf_header *header = &session->header;
1062edbe9817SJiri Olsa 	struct bt_ctf_writer *writer = cw->writer;
1063edbe9817SJiri Olsa 
1064edbe9817SJiri Olsa #define ADD(__n, __v)							\
1065edbe9817SJiri Olsa do {									\
1066edbe9817SJiri Olsa 	if (bt_ctf_writer_add_environment_field(writer, __n, __v))	\
1067edbe9817SJiri Olsa 		return -1;						\
1068edbe9817SJiri Olsa } while (0)
1069edbe9817SJiri Olsa 
1070edbe9817SJiri Olsa 	ADD("host",    header->env.hostname);
1071edbe9817SJiri Olsa 	ADD("sysname", "Linux");
1072edbe9817SJiri Olsa 	ADD("release", header->env.os_release);
1073edbe9817SJiri Olsa 	ADD("version", header->env.version);
1074edbe9817SJiri Olsa 	ADD("machine", header->env.arch);
1075edbe9817SJiri Olsa 	ADD("domain", "kernel");
1076edbe9817SJiri Olsa 	ADD("tracer_name", "perf");
1077edbe9817SJiri Olsa 
1078edbe9817SJiri Olsa #undef ADD
1079edbe9817SJiri Olsa 	return 0;
1080edbe9817SJiri Olsa }
1081edbe9817SJiri Olsa 
1082edbe9817SJiri Olsa static int ctf_writer__setup_clock(struct ctf_writer *cw)
1083edbe9817SJiri Olsa {
1084edbe9817SJiri Olsa 	struct bt_ctf_clock *clock = cw->clock;
1085edbe9817SJiri Olsa 
1086edbe9817SJiri Olsa 	bt_ctf_clock_set_description(clock, "perf clock");
1087edbe9817SJiri Olsa 
1088edbe9817SJiri Olsa #define SET(__n, __v)				\
1089edbe9817SJiri Olsa do {						\
1090edbe9817SJiri Olsa 	if (bt_ctf_clock_set_##__n(clock, __v))	\
1091edbe9817SJiri Olsa 		return -1;			\
1092edbe9817SJiri Olsa } while (0)
1093edbe9817SJiri Olsa 
1094edbe9817SJiri Olsa 	SET(frequency,   1000000000);
1095edbe9817SJiri Olsa 	SET(offset_s,    0);
1096edbe9817SJiri Olsa 	SET(offset,      0);
1097edbe9817SJiri Olsa 	SET(precision,   10);
1098edbe9817SJiri Olsa 	SET(is_absolute, 0);
1099edbe9817SJiri Olsa 
1100edbe9817SJiri Olsa #undef SET
1101edbe9817SJiri Olsa 	return 0;
1102edbe9817SJiri Olsa }
1103edbe9817SJiri Olsa 
1104edbe9817SJiri Olsa static struct bt_ctf_field_type *create_int_type(int size, bool sign, bool hex)
1105edbe9817SJiri Olsa {
1106edbe9817SJiri Olsa 	struct bt_ctf_field_type *type;
1107edbe9817SJiri Olsa 
1108edbe9817SJiri Olsa 	type = bt_ctf_field_type_integer_create(size);
1109edbe9817SJiri Olsa 	if (!type)
1110edbe9817SJiri Olsa 		return NULL;
1111edbe9817SJiri Olsa 
1112edbe9817SJiri Olsa 	if (sign &&
1113edbe9817SJiri Olsa 	    bt_ctf_field_type_integer_set_signed(type, 1))
1114edbe9817SJiri Olsa 		goto err;
1115edbe9817SJiri Olsa 
1116edbe9817SJiri Olsa 	if (hex &&
1117edbe9817SJiri Olsa 	    bt_ctf_field_type_integer_set_base(type, BT_CTF_INTEGER_BASE_HEXADECIMAL))
1118edbe9817SJiri Olsa 		goto err;
1119edbe9817SJiri Olsa 
1120f8dd2d5fSWang Nan #if __BYTE_ORDER == __BIG_ENDIAN
1121f8dd2d5fSWang Nan 	bt_ctf_field_type_set_byte_order(type, BT_CTF_BYTE_ORDER_BIG_ENDIAN);
1122f8dd2d5fSWang Nan #else
1123f8dd2d5fSWang Nan 	bt_ctf_field_type_set_byte_order(type, BT_CTF_BYTE_ORDER_LITTLE_ENDIAN);
1124f8dd2d5fSWang Nan #endif
1125f8dd2d5fSWang Nan 
1126edbe9817SJiri Olsa 	pr2("Created type: INTEGER %d-bit %ssigned %s\n",
1127edbe9817SJiri Olsa 	    size, sign ? "un" : "", hex ? "hex" : "");
1128edbe9817SJiri Olsa 	return type;
1129edbe9817SJiri Olsa 
1130edbe9817SJiri Olsa err:
1131edbe9817SJiri Olsa 	bt_ctf_field_type_put(type);
1132edbe9817SJiri Olsa 	return NULL;
1133edbe9817SJiri Olsa }
1134edbe9817SJiri Olsa 
1135edbe9817SJiri Olsa static void ctf_writer__cleanup_data(struct ctf_writer *cw)
1136edbe9817SJiri Olsa {
1137edbe9817SJiri Olsa 	unsigned int i;
1138edbe9817SJiri Olsa 
1139edbe9817SJiri Olsa 	for (i = 0; i < ARRAY_SIZE(cw->data.array); i++)
1140edbe9817SJiri Olsa 		bt_ctf_field_type_put(cw->data.array[i]);
1141edbe9817SJiri Olsa }
1142edbe9817SJiri Olsa 
1143edbe9817SJiri Olsa static int ctf_writer__init_data(struct ctf_writer *cw)
1144edbe9817SJiri Olsa {
1145edbe9817SJiri Olsa #define CREATE_INT_TYPE(type, size, sign, hex)		\
1146edbe9817SJiri Olsa do {							\
1147edbe9817SJiri Olsa 	(type) = create_int_type(size, sign, hex);	\
1148edbe9817SJiri Olsa 	if (!(type))					\
1149edbe9817SJiri Olsa 		goto err;				\
1150edbe9817SJiri Olsa } while (0)
1151edbe9817SJiri Olsa 
1152edbe9817SJiri Olsa 	CREATE_INT_TYPE(cw->data.s64, 64, true,  false);
1153edbe9817SJiri Olsa 	CREATE_INT_TYPE(cw->data.u64, 64, false, false);
1154edbe9817SJiri Olsa 	CREATE_INT_TYPE(cw->data.s32, 32, true,  false);
1155edbe9817SJiri Olsa 	CREATE_INT_TYPE(cw->data.u32, 32, false, false);
115626812d46SWang Nan 	CREATE_INT_TYPE(cw->data.u32_hex, 32, false, true);
1157edbe9817SJiri Olsa 	CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true);
1158edbe9817SJiri Olsa 
1159edbe9817SJiri Olsa 	cw->data.string  = bt_ctf_field_type_string_create();
1160edbe9817SJiri Olsa 	if (cw->data.string)
1161edbe9817SJiri Olsa 		return 0;
1162edbe9817SJiri Olsa 
1163edbe9817SJiri Olsa err:
1164edbe9817SJiri Olsa 	ctf_writer__cleanup_data(cw);
1165edbe9817SJiri Olsa 	pr_err("Failed to create data types.\n");
1166edbe9817SJiri Olsa 	return -1;
1167edbe9817SJiri Olsa }
1168edbe9817SJiri Olsa 
1169edbe9817SJiri Olsa static void ctf_writer__cleanup(struct ctf_writer *cw)
1170edbe9817SJiri Olsa {
1171edbe9817SJiri Olsa 	ctf_writer__cleanup_data(cw);
1172edbe9817SJiri Olsa 
1173edbe9817SJiri Olsa 	bt_ctf_clock_put(cw->clock);
117490e129ffSSebastian Andrzej Siewior 	free_streams(cw);
1175edbe9817SJiri Olsa 	bt_ctf_stream_class_put(cw->stream_class);
1176edbe9817SJiri Olsa 	bt_ctf_writer_put(cw->writer);
1177edbe9817SJiri Olsa 
1178edbe9817SJiri Olsa 	/* and NULL all the pointers */
1179edbe9817SJiri Olsa 	memset(cw, 0, sizeof(*cw));
1180edbe9817SJiri Olsa }
1181edbe9817SJiri Olsa 
1182edbe9817SJiri Olsa static int ctf_writer__init(struct ctf_writer *cw, const char *path)
1183edbe9817SJiri Olsa {
1184edbe9817SJiri Olsa 	struct bt_ctf_writer		*writer;
1185edbe9817SJiri Olsa 	struct bt_ctf_stream_class	*stream_class;
1186edbe9817SJiri Olsa 	struct bt_ctf_clock		*clock;
118790e129ffSSebastian Andrzej Siewior 	struct bt_ctf_field_type	*pkt_ctx_type;
118890e129ffSSebastian Andrzej Siewior 	int				ret;
1189edbe9817SJiri Olsa 
1190edbe9817SJiri Olsa 	/* CTF writer */
1191edbe9817SJiri Olsa 	writer = bt_ctf_writer_create(path);
1192edbe9817SJiri Olsa 	if (!writer)
1193edbe9817SJiri Olsa 		goto err;
1194edbe9817SJiri Olsa 
1195edbe9817SJiri Olsa 	cw->writer = writer;
1196edbe9817SJiri Olsa 
1197edbe9817SJiri Olsa 	/* CTF clock */
1198edbe9817SJiri Olsa 	clock = bt_ctf_clock_create("perf_clock");
1199edbe9817SJiri Olsa 	if (!clock) {
1200edbe9817SJiri Olsa 		pr("Failed to create CTF clock.\n");
1201edbe9817SJiri Olsa 		goto err_cleanup;
1202edbe9817SJiri Olsa 	}
1203edbe9817SJiri Olsa 
1204edbe9817SJiri Olsa 	cw->clock = clock;
1205edbe9817SJiri Olsa 
1206edbe9817SJiri Olsa 	if (ctf_writer__setup_clock(cw)) {
1207edbe9817SJiri Olsa 		pr("Failed to setup CTF clock.\n");
1208edbe9817SJiri Olsa 		goto err_cleanup;
1209edbe9817SJiri Olsa 	}
1210edbe9817SJiri Olsa 
1211edbe9817SJiri Olsa 	/* CTF stream class */
1212edbe9817SJiri Olsa 	stream_class = bt_ctf_stream_class_create("perf_stream");
1213edbe9817SJiri Olsa 	if (!stream_class) {
1214edbe9817SJiri Olsa 		pr("Failed to create CTF stream class.\n");
1215edbe9817SJiri Olsa 		goto err_cleanup;
1216edbe9817SJiri Olsa 	}
1217edbe9817SJiri Olsa 
1218edbe9817SJiri Olsa 	cw->stream_class = stream_class;
1219edbe9817SJiri Olsa 
1220edbe9817SJiri Olsa 	/* CTF clock stream setup */
1221edbe9817SJiri Olsa 	if (bt_ctf_stream_class_set_clock(stream_class, clock)) {
1222edbe9817SJiri Olsa 		pr("Failed to assign CTF clock to stream class.\n");
1223edbe9817SJiri Olsa 		goto err_cleanup;
1224edbe9817SJiri Olsa 	}
1225edbe9817SJiri Olsa 
1226edbe9817SJiri Olsa 	if (ctf_writer__init_data(cw))
1227edbe9817SJiri Olsa 		goto err_cleanup;
1228edbe9817SJiri Olsa 
122990e129ffSSebastian Andrzej Siewior 	/* Add cpu_id for packet context */
123090e129ffSSebastian Andrzej Siewior 	pkt_ctx_type = bt_ctf_stream_class_get_packet_context_type(stream_class);
123190e129ffSSebastian Andrzej Siewior 	if (!pkt_ctx_type)
1232edbe9817SJiri Olsa 		goto err_cleanup;
1233edbe9817SJiri Olsa 
123490e129ffSSebastian Andrzej Siewior 	ret = bt_ctf_field_type_structure_add_field(pkt_ctx_type, cw->data.u32, "cpu_id");
123590e129ffSSebastian Andrzej Siewior 	bt_ctf_field_type_put(pkt_ctx_type);
123690e129ffSSebastian Andrzej Siewior 	if (ret)
123790e129ffSSebastian Andrzej Siewior 		goto err_cleanup;
1238edbe9817SJiri Olsa 
1239edbe9817SJiri Olsa 	/* CTF clock writer setup */
1240edbe9817SJiri Olsa 	if (bt_ctf_writer_add_clock(writer, clock)) {
1241edbe9817SJiri Olsa 		pr("Failed to assign CTF clock to writer.\n");
1242edbe9817SJiri Olsa 		goto err_cleanup;
1243edbe9817SJiri Olsa 	}
1244edbe9817SJiri Olsa 
1245edbe9817SJiri Olsa 	return 0;
1246edbe9817SJiri Olsa 
1247edbe9817SJiri Olsa err_cleanup:
1248edbe9817SJiri Olsa 	ctf_writer__cleanup(cw);
1249edbe9817SJiri Olsa err:
1250edbe9817SJiri Olsa 	pr_err("Failed to setup CTF writer.\n");
1251edbe9817SJiri Olsa 	return -1;
1252edbe9817SJiri Olsa }
1253edbe9817SJiri Olsa 
125490e129ffSSebastian Andrzej Siewior static int ctf_writer__flush_streams(struct ctf_writer *cw)
125590e129ffSSebastian Andrzej Siewior {
125690e129ffSSebastian Andrzej Siewior 	int cpu, ret = 0;
125790e129ffSSebastian Andrzej Siewior 
125890e129ffSSebastian Andrzej Siewior 	for (cpu = 0; cpu < cw->stream_cnt && !ret; cpu++)
125990e129ffSSebastian Andrzej Siewior 		ret = ctf_stream__flush(cw->stream[cpu]);
126090e129ffSSebastian Andrzej Siewior 
126190e129ffSSebastian Andrzej Siewior 	return ret;
126290e129ffSSebastian Andrzej Siewior }
126390e129ffSSebastian Andrzej Siewior 
12648fa46753SJiri Olsa static int convert__config(const char *var, const char *value, void *cb)
12658fa46753SJiri Olsa {
12668fa46753SJiri Olsa 	struct convert *c = cb;
12678fa46753SJiri Olsa 
12688fa46753SJiri Olsa 	if (!strcmp(var, "convert.queue-size")) {
12698fa46753SJiri Olsa 		c->queue_size = perf_config_u64(var, value);
12708fa46753SJiri Olsa 		return 0;
12718fa46753SJiri Olsa 	}
12728fa46753SJiri Olsa 
1273b8cbb349SWang Nan 	return 0;
12748fa46753SJiri Olsa }
12758fa46753SJiri Olsa 
1276bd05954bSYunlong Song int bt_convert__perf2ctf(const char *input, const char *path, bool force)
1277edbe9817SJiri Olsa {
1278edbe9817SJiri Olsa 	struct perf_session *session;
1279edbe9817SJiri Olsa 	struct perf_data_file file = {
1280edbe9817SJiri Olsa 		.path = input,
1281edbe9817SJiri Olsa 		.mode = PERF_DATA_MODE_READ,
1282bd05954bSYunlong Song 		.force = force,
1283edbe9817SJiri Olsa 	};
1284edbe9817SJiri Olsa 	struct convert c = {
1285edbe9817SJiri Olsa 		.tool = {
1286edbe9817SJiri Olsa 			.sample          = process_sample_event,
1287edbe9817SJiri Olsa 			.mmap            = perf_event__process_mmap,
1288edbe9817SJiri Olsa 			.mmap2           = perf_event__process_mmap2,
1289edbe9817SJiri Olsa 			.comm            = perf_event__process_comm,
1290edbe9817SJiri Olsa 			.exit            = perf_event__process_exit,
1291edbe9817SJiri Olsa 			.fork            = perf_event__process_fork,
1292edbe9817SJiri Olsa 			.lost            = perf_event__process_lost,
1293edbe9817SJiri Olsa 			.tracing_data    = perf_event__process_tracing_data,
1294edbe9817SJiri Olsa 			.build_id        = perf_event__process_build_id,
1295edbe9817SJiri Olsa 			.ordered_events  = true,
1296edbe9817SJiri Olsa 			.ordering_requires_timestamps = true,
1297edbe9817SJiri Olsa 		},
1298edbe9817SJiri Olsa 	};
1299edbe9817SJiri Olsa 	struct ctf_writer *cw = &c.writer;
1300edbe9817SJiri Olsa 	int err = -1;
1301edbe9817SJiri Olsa 
13028fa46753SJiri Olsa 	perf_config(convert__config, &c);
13038fa46753SJiri Olsa 
1304edbe9817SJiri Olsa 	/* CTF writer */
1305edbe9817SJiri Olsa 	if (ctf_writer__init(cw, path))
1306edbe9817SJiri Olsa 		return -1;
1307edbe9817SJiri Olsa 
1308edbe9817SJiri Olsa 	/* perf.data session */
1309b7b61cbeSArnaldo Carvalho de Melo 	session = perf_session__new(&file, 0, &c.tool);
1310edbe9817SJiri Olsa 	if (!session)
1311edbe9817SJiri Olsa 		goto free_writer;
1312edbe9817SJiri Olsa 
13138fa46753SJiri Olsa 	if (c.queue_size) {
13148fa46753SJiri Olsa 		ordered_events__set_alloc_size(&session->ordered_events,
13158fa46753SJiri Olsa 					       c.queue_size);
13168fa46753SJiri Olsa 	}
13178fa46753SJiri Olsa 
1318edbe9817SJiri Olsa 	/* CTF writer env/clock setup  */
1319edbe9817SJiri Olsa 	if (ctf_writer__setup_env(cw, session))
1320edbe9817SJiri Olsa 		goto free_session;
1321edbe9817SJiri Olsa 
1322edbe9817SJiri Olsa 	/* CTF events setup */
1323edbe9817SJiri Olsa 	if (setup_events(cw, session))
1324edbe9817SJiri Olsa 		goto free_session;
1325edbe9817SJiri Olsa 
132690e129ffSSebastian Andrzej Siewior 	if (setup_streams(cw, session))
132790e129ffSSebastian Andrzej Siewior 		goto free_session;
132890e129ffSSebastian Andrzej Siewior 
1329b7b61cbeSArnaldo Carvalho de Melo 	err = perf_session__process_events(session);
1330edbe9817SJiri Olsa 	if (!err)
133190e129ffSSebastian Andrzej Siewior 		err = ctf_writer__flush_streams(cw);
1332c2141055SHe Kuang 	else
1333c2141055SHe Kuang 		pr_err("Error during conversion.\n");
1334edbe9817SJiri Olsa 
1335edbe9817SJiri Olsa 	fprintf(stderr,
1336edbe9817SJiri Olsa 		"[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
1337edbe9817SJiri Olsa 		file.path, path);
1338edbe9817SJiri Olsa 
1339edbe9817SJiri Olsa 	fprintf(stderr,
1340edbe9817SJiri Olsa 		"[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples) ]\n",
1341edbe9817SJiri Olsa 		(double) c.events_size / 1024.0 / 1024.0,
1342edbe9817SJiri Olsa 		c.events_count);
1343edbe9817SJiri Olsa 
13445141d735SWang Nan 	cleanup_events(session);
1345c2141055SHe Kuang 	perf_session__delete(session);
1346c2141055SHe Kuang 	ctf_writer__cleanup(cw);
1347c2141055SHe Kuang 
1348c2141055SHe Kuang 	return err;
1349c2141055SHe Kuang 
1350edbe9817SJiri Olsa free_session:
1351edbe9817SJiri Olsa 	perf_session__delete(session);
1352edbe9817SJiri Olsa free_writer:
1353edbe9817SJiri Olsa 	ctf_writer__cleanup(cw);
1354c2141055SHe Kuang 	pr_err("Error during conversion setup.\n");
1355edbe9817SJiri Olsa 	return err;
1356edbe9817SJiri Olsa }
1357