xref: /linux/tools/perf/util/data-convert-bt.c (revision bb39ccb204cc2e8135660b9cb768ffcf242bf33e)
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 
10a43783aeSArnaldo Carvalho de Melo #include <errno.h>
11fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
12edbe9817SJiri Olsa #include <linux/compiler.h>
13877a7a11SArnaldo Carvalho de Melo #include <linux/kernel.h>
14edbe9817SJiri Olsa #include <babeltrace/ctf-writer/writer.h>
15edbe9817SJiri Olsa #include <babeltrace/ctf-writer/clock.h>
16edbe9817SJiri Olsa #include <babeltrace/ctf-writer/stream.h>
17edbe9817SJiri Olsa #include <babeltrace/ctf-writer/event.h>
18edbe9817SJiri Olsa #include <babeltrace/ctf-writer/event-types.h>
19edbe9817SJiri Olsa #include <babeltrace/ctf-writer/event-fields.h>
20e0a7cce5SWang Nan #include <babeltrace/ctf-ir/utils.h>
21edbe9817SJiri Olsa #include <babeltrace/ctf/events.h>
22edbe9817SJiri Olsa #include <traceevent/event-parse.h>
23edbe9817SJiri Olsa #include "asm/bug.h"
24edbe9817SJiri Olsa #include "data-convert-bt.h"
25edbe9817SJiri Olsa #include "session.h"
26edbe9817SJiri Olsa #include "util.h"
27edbe9817SJiri Olsa #include "debug.h"
28edbe9817SJiri Olsa #include "tool.h"
29edbe9817SJiri Olsa #include "evlist.h"
30edbe9817SJiri Olsa #include "evsel.h"
31edbe9817SJiri Olsa #include "machine.h"
32f6c12a00SJiri Olsa #include "config.h"
333d689ed6SArnaldo Carvalho de Melo #include "sane_ctype.h"
34edbe9817SJiri Olsa 
35edbe9817SJiri Olsa #define pr_N(n, fmt, ...) \
36edbe9817SJiri Olsa 	eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
37edbe9817SJiri Olsa 
38edbe9817SJiri Olsa #define pr(fmt, ...)  pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
39edbe9817SJiri Olsa #define pr2(fmt, ...) pr_N(2, pr_fmt(fmt), ##__VA_ARGS__)
40edbe9817SJiri Olsa 
41edbe9817SJiri Olsa #define pr_time2(t, fmt, ...) pr_time_N(2, debug_data_convert, t, pr_fmt(fmt), ##__VA_ARGS__)
42edbe9817SJiri Olsa 
43edbe9817SJiri Olsa struct evsel_priv {
44edbe9817SJiri Olsa 	struct bt_ctf_event_class *event_class;
45edbe9817SJiri Olsa };
46edbe9817SJiri Olsa 
4790e129ffSSebastian Andrzej Siewior #define MAX_CPUS	4096
4890e129ffSSebastian Andrzej Siewior 
4990e129ffSSebastian Andrzej Siewior struct ctf_stream {
5090e129ffSSebastian Andrzej Siewior 	struct bt_ctf_stream *stream;
5190e129ffSSebastian Andrzej Siewior 	int cpu;
5289e5fa88SJiri Olsa 	u32 count;
5390e129ffSSebastian Andrzej Siewior };
5490e129ffSSebastian Andrzej Siewior 
55edbe9817SJiri Olsa struct ctf_writer {
56edbe9817SJiri Olsa 	/* writer primitives */
57edbe9817SJiri Olsa 	struct bt_ctf_writer		 *writer;
5890e129ffSSebastian Andrzej Siewior 	struct ctf_stream		**stream;
5990e129ffSSebastian Andrzej Siewior 	int				  stream_cnt;
60edbe9817SJiri Olsa 	struct bt_ctf_stream_class	 *stream_class;
61edbe9817SJiri Olsa 	struct bt_ctf_clock		 *clock;
62edbe9817SJiri Olsa 
63edbe9817SJiri Olsa 	/* data types */
64edbe9817SJiri Olsa 	union {
65edbe9817SJiri Olsa 		struct {
66edbe9817SJiri Olsa 			struct bt_ctf_field_type	*s64;
67edbe9817SJiri Olsa 			struct bt_ctf_field_type	*u64;
68edbe9817SJiri Olsa 			struct bt_ctf_field_type	*s32;
69edbe9817SJiri Olsa 			struct bt_ctf_field_type	*u32;
70edbe9817SJiri Olsa 			struct bt_ctf_field_type	*string;
7126812d46SWang Nan 			struct bt_ctf_field_type	*u32_hex;
72edbe9817SJiri Olsa 			struct bt_ctf_field_type	*u64_hex;
73edbe9817SJiri Olsa 		};
74edbe9817SJiri Olsa 		struct bt_ctf_field_type *array[6];
75edbe9817SJiri Olsa 	} data;
76f5a08cedSWang Nan 	struct bt_ctf_event_class	*comm_class;
77ebccba3fSWang Nan 	struct bt_ctf_event_class	*exit_class;
78ebccba3fSWang Nan 	struct bt_ctf_event_class	*fork_class;
79f9f6f2a9SGeneviève Bastien 	struct bt_ctf_event_class	*mmap_class;
80f9f6f2a9SGeneviève Bastien 	struct bt_ctf_event_class	*mmap2_class;
81edbe9817SJiri Olsa };
82edbe9817SJiri Olsa 
83edbe9817SJiri Olsa struct convert {
84edbe9817SJiri Olsa 	struct perf_tool	tool;
85edbe9817SJiri Olsa 	struct ctf_writer	writer;
86edbe9817SJiri Olsa 
87edbe9817SJiri Olsa 	u64			events_size;
88edbe9817SJiri Olsa 	u64			events_count;
898ee4c46cSWang Nan 	u64			non_sample_count;
908fa46753SJiri Olsa 
918fa46753SJiri Olsa 	/* Ordered events configured queue size. */
928fa46753SJiri Olsa 	u64			queue_size;
93edbe9817SJiri Olsa };
94edbe9817SJiri Olsa 
95edbe9817SJiri Olsa static int value_set(struct bt_ctf_field_type *type,
96edbe9817SJiri Olsa 		     struct bt_ctf_event *event,
97edbe9817SJiri Olsa 		     const char *name, u64 val)
98edbe9817SJiri Olsa {
99edbe9817SJiri Olsa 	struct bt_ctf_field *field;
100edbe9817SJiri Olsa 	bool sign = bt_ctf_field_type_integer_get_signed(type);
101edbe9817SJiri Olsa 	int ret;
102edbe9817SJiri Olsa 
103edbe9817SJiri Olsa 	field = bt_ctf_field_create(type);
104edbe9817SJiri Olsa 	if (!field) {
105edbe9817SJiri Olsa 		pr_err("failed to create a field %s\n", name);
106edbe9817SJiri Olsa 		return -1;
107edbe9817SJiri Olsa 	}
108edbe9817SJiri Olsa 
109edbe9817SJiri Olsa 	if (sign) {
110edbe9817SJiri Olsa 		ret = bt_ctf_field_signed_integer_set_value(field, val);
111edbe9817SJiri Olsa 		if (ret) {
112edbe9817SJiri Olsa 			pr_err("failed to set field value %s\n", name);
113edbe9817SJiri Olsa 			goto err;
114edbe9817SJiri Olsa 		}
115edbe9817SJiri Olsa 	} else {
116edbe9817SJiri Olsa 		ret = bt_ctf_field_unsigned_integer_set_value(field, val);
117edbe9817SJiri Olsa 		if (ret) {
118edbe9817SJiri Olsa 			pr_err("failed to set field value %s\n", name);
119edbe9817SJiri Olsa 			goto err;
120edbe9817SJiri Olsa 		}
121edbe9817SJiri Olsa 	}
122edbe9817SJiri Olsa 
123edbe9817SJiri Olsa 	ret = bt_ctf_event_set_payload(event, name, field);
124edbe9817SJiri Olsa 	if (ret) {
125edbe9817SJiri Olsa 		pr_err("failed to set payload %s\n", name);
126edbe9817SJiri Olsa 		goto err;
127edbe9817SJiri Olsa 	}
128edbe9817SJiri Olsa 
129edbe9817SJiri Olsa 	pr2("  SET [%s = %" PRIu64 "]\n", name, val);
130edbe9817SJiri Olsa 
131edbe9817SJiri Olsa err:
132edbe9817SJiri Olsa 	bt_ctf_field_put(field);
133edbe9817SJiri Olsa 	return ret;
134edbe9817SJiri Olsa }
135edbe9817SJiri Olsa 
136edbe9817SJiri Olsa #define __FUNC_VALUE_SET(_name, _val_type)				\
137edbe9817SJiri Olsa static __maybe_unused int value_set_##_name(struct ctf_writer *cw,	\
138edbe9817SJiri Olsa 			     struct bt_ctf_event *event,		\
139edbe9817SJiri Olsa 			     const char *name,				\
140edbe9817SJiri Olsa 			     _val_type val)				\
141edbe9817SJiri Olsa {									\
142edbe9817SJiri Olsa 	struct bt_ctf_field_type *type = cw->data._name;		\
143edbe9817SJiri Olsa 	return value_set(type, event, name, (u64) val);			\
144edbe9817SJiri Olsa }
145edbe9817SJiri Olsa 
146edbe9817SJiri Olsa #define FUNC_VALUE_SET(_name) __FUNC_VALUE_SET(_name, _name)
147edbe9817SJiri Olsa 
148edbe9817SJiri Olsa FUNC_VALUE_SET(s32)
149edbe9817SJiri Olsa FUNC_VALUE_SET(u32)
150edbe9817SJiri Olsa FUNC_VALUE_SET(s64)
151edbe9817SJiri Olsa FUNC_VALUE_SET(u64)
152edbe9817SJiri Olsa __FUNC_VALUE_SET(u64_hex, u64)
153edbe9817SJiri Olsa 
154069ee5c4SWang Nan static int string_set_value(struct bt_ctf_field *field, const char *string);
155069ee5c4SWang Nan static __maybe_unused int
156069ee5c4SWang Nan value_set_string(struct ctf_writer *cw, struct bt_ctf_event *event,
157069ee5c4SWang Nan 		 const char *name, const char *string)
158069ee5c4SWang Nan {
159069ee5c4SWang Nan 	struct bt_ctf_field_type *type = cw->data.string;
160069ee5c4SWang Nan 	struct bt_ctf_field *field;
161069ee5c4SWang Nan 	int ret = 0;
162069ee5c4SWang Nan 
163069ee5c4SWang Nan 	field = bt_ctf_field_create(type);
164069ee5c4SWang Nan 	if (!field) {
165069ee5c4SWang Nan 		pr_err("failed to create a field %s\n", name);
166069ee5c4SWang Nan 		return -1;
167069ee5c4SWang Nan 	}
168069ee5c4SWang Nan 
169069ee5c4SWang Nan 	ret = string_set_value(field, string);
170069ee5c4SWang Nan 	if (ret) {
171069ee5c4SWang Nan 		pr_err("failed to set value %s\n", name);
172069ee5c4SWang Nan 		goto err_put_field;
173069ee5c4SWang Nan 	}
174069ee5c4SWang Nan 
175069ee5c4SWang Nan 	ret = bt_ctf_event_set_payload(event, name, field);
176069ee5c4SWang Nan 	if (ret)
177069ee5c4SWang Nan 		pr_err("failed to set payload %s\n", name);
178069ee5c4SWang Nan 
179069ee5c4SWang Nan err_put_field:
180069ee5c4SWang Nan 	bt_ctf_field_put(field);
181069ee5c4SWang Nan 	return ret;
182069ee5c4SWang Nan }
183069ee5c4SWang Nan 
18469364727SSebastian Andrzej Siewior static struct bt_ctf_field_type*
1852c92f982STzvetomir Stoyanov (VMware) get_tracepoint_field_type(struct ctf_writer *cw, struct tep_format_field *field)
18669364727SSebastian Andrzej Siewior {
18769364727SSebastian Andrzej Siewior 	unsigned long flags = field->flags;
18869364727SSebastian Andrzej Siewior 
189*bb39ccb2STzvetomir Stoyanov (VMware) 	if (flags & TEP_FIELD_IS_STRING)
19069364727SSebastian Andrzej Siewior 		return cw->data.string;
19169364727SSebastian Andrzej Siewior 
192*bb39ccb2STzvetomir Stoyanov (VMware) 	if (!(flags & TEP_FIELD_IS_SIGNED)) {
19369364727SSebastian Andrzej Siewior 		/* unsigned long are mostly pointers */
194*bb39ccb2STzvetomir Stoyanov (VMware) 		if (flags & TEP_FIELD_IS_LONG || flags & TEP_FIELD_IS_POINTER)
19569364727SSebastian Andrzej Siewior 			return cw->data.u64_hex;
19669364727SSebastian Andrzej Siewior 	}
19769364727SSebastian Andrzej Siewior 
198*bb39ccb2STzvetomir Stoyanov (VMware) 	if (flags & TEP_FIELD_IS_SIGNED) {
19969364727SSebastian Andrzej Siewior 		if (field->size == 8)
20069364727SSebastian Andrzej Siewior 			return cw->data.s64;
20169364727SSebastian Andrzej Siewior 		else
20269364727SSebastian Andrzej Siewior 			return cw->data.s32;
20369364727SSebastian Andrzej Siewior 	}
20469364727SSebastian Andrzej Siewior 
20569364727SSebastian Andrzej Siewior 	if (field->size == 8)
20669364727SSebastian Andrzej Siewior 		return cw->data.u64;
20769364727SSebastian Andrzej Siewior 	else
20869364727SSebastian Andrzej Siewior 		return cw->data.u32;
20969364727SSebastian Andrzej Siewior }
21069364727SSebastian Andrzej Siewior 
211d4ae4213SWang Nan static unsigned long long adjust_signedness(unsigned long long value_int, int size)
212d4ae4213SWang Nan {
213d4ae4213SWang Nan 	unsigned long long value_mask;
214d4ae4213SWang Nan 
215d4ae4213SWang Nan 	/*
216d4ae4213SWang Nan 	 * value_mask = (1 << (size * 8 - 1)) - 1.
217d4ae4213SWang Nan 	 * Directly set value_mask for code readers.
218d4ae4213SWang Nan 	 */
219d4ae4213SWang Nan 	switch (size) {
220d4ae4213SWang Nan 	case 1:
221d4ae4213SWang Nan 		value_mask = 0x7fULL;
222d4ae4213SWang Nan 		break;
223d4ae4213SWang Nan 	case 2:
224d4ae4213SWang Nan 		value_mask = 0x7fffULL;
225d4ae4213SWang Nan 		break;
226d4ae4213SWang Nan 	case 4:
227d4ae4213SWang Nan 		value_mask = 0x7fffffffULL;
228d4ae4213SWang Nan 		break;
229d4ae4213SWang Nan 	case 8:
230d4ae4213SWang Nan 		/*
231d4ae4213SWang Nan 		 * For 64 bit value, return it self. There is no need
232d4ae4213SWang Nan 		 * to fill high bit.
233d4ae4213SWang Nan 		 */
234d4ae4213SWang Nan 		/* Fall through */
235d4ae4213SWang Nan 	default:
236d4ae4213SWang Nan 		/* BUG! */
237d4ae4213SWang Nan 		return value_int;
238d4ae4213SWang Nan 	}
239d4ae4213SWang Nan 
240d4ae4213SWang Nan 	/* If it is a positive value, don't adjust. */
241d4ae4213SWang Nan 	if ((value_int & (~0ULL - value_mask)) == 0)
242d4ae4213SWang Nan 		return value_int;
243d4ae4213SWang Nan 
244d4ae4213SWang Nan 	/* Fill upper part of value_int with 1 to make it a negative long long. */
245d4ae4213SWang Nan 	return (value_int & value_mask) | ~value_mask;
246d4ae4213SWang Nan }
247d4ae4213SWang Nan 
2485ea5888bSWang Nan static int string_set_value(struct bt_ctf_field *field, const char *string)
2495ea5888bSWang Nan {
2505ea5888bSWang Nan 	char *buffer = NULL;
2515ea5888bSWang Nan 	size_t len = strlen(string), i, p;
2525ea5888bSWang Nan 	int err;
2535ea5888bSWang Nan 
2545ea5888bSWang Nan 	for (i = p = 0; i < len; i++, p++) {
2555ea5888bSWang Nan 		if (isprint(string[i])) {
2565ea5888bSWang Nan 			if (!buffer)
2575ea5888bSWang Nan 				continue;
2585ea5888bSWang Nan 			buffer[p] = string[i];
2595ea5888bSWang Nan 		} else {
2605ea5888bSWang Nan 			char numstr[5];
2615ea5888bSWang Nan 
2625ea5888bSWang Nan 			snprintf(numstr, sizeof(numstr), "\\x%02x",
2635ea5888bSWang Nan 				 (unsigned int)(string[i]) & 0xff);
2645ea5888bSWang Nan 
2655ea5888bSWang Nan 			if (!buffer) {
2665ea5888bSWang Nan 				buffer = zalloc(i + (len - i) * 4 + 2);
2675ea5888bSWang Nan 				if (!buffer) {
2685ea5888bSWang Nan 					pr_err("failed to set unprintable string '%s'\n", string);
2695ea5888bSWang Nan 					return bt_ctf_field_string_set_value(field, "UNPRINTABLE-STRING");
2705ea5888bSWang Nan 				}
2715ea5888bSWang Nan 				if (i > 0)
2725ea5888bSWang Nan 					strncpy(buffer, string, i);
2735ea5888bSWang Nan 			}
2745ea5888bSWang Nan 			strncat(buffer + p, numstr, 4);
2755ea5888bSWang Nan 			p += 3;
2765ea5888bSWang Nan 		}
2775ea5888bSWang Nan 	}
2785ea5888bSWang Nan 
2795ea5888bSWang Nan 	if (!buffer)
2805ea5888bSWang Nan 		return bt_ctf_field_string_set_value(field, string);
2815ea5888bSWang Nan 	err = bt_ctf_field_string_set_value(field, buffer);
2825ea5888bSWang Nan 	free(buffer);
2835ea5888bSWang Nan 	return err;
2845ea5888bSWang Nan }
2855ea5888bSWang Nan 
28669364727SSebastian Andrzej Siewior static int add_tracepoint_field_value(struct ctf_writer *cw,
28769364727SSebastian Andrzej Siewior 				      struct bt_ctf_event_class *event_class,
28869364727SSebastian Andrzej Siewior 				      struct bt_ctf_event *event,
28969364727SSebastian Andrzej Siewior 				      struct perf_sample *sample,
2902c92f982STzvetomir Stoyanov (VMware) 				      struct tep_format_field *fmtf)
29169364727SSebastian Andrzej Siewior {
29269364727SSebastian Andrzej Siewior 	struct bt_ctf_field_type *type;
29369364727SSebastian Andrzej Siewior 	struct bt_ctf_field *array_field;
29469364727SSebastian Andrzej Siewior 	struct bt_ctf_field *field;
29569364727SSebastian Andrzej Siewior 	const char *name = fmtf->name;
29669364727SSebastian Andrzej Siewior 	void *data = sample->raw_data;
29769364727SSebastian Andrzej Siewior 	unsigned long flags = fmtf->flags;
29869364727SSebastian Andrzej Siewior 	unsigned int n_items;
29969364727SSebastian Andrzej Siewior 	unsigned int i;
30069364727SSebastian Andrzej Siewior 	unsigned int offset;
30169364727SSebastian Andrzej Siewior 	unsigned int len;
30269364727SSebastian Andrzej Siewior 	int ret;
30369364727SSebastian Andrzej Siewior 
304e0a7cce5SWang Nan 	name = fmtf->alias;
30569364727SSebastian Andrzej Siewior 	offset = fmtf->offset;
30669364727SSebastian Andrzej Siewior 	len = fmtf->size;
307*bb39ccb2STzvetomir Stoyanov (VMware) 	if (flags & TEP_FIELD_IS_STRING)
308*bb39ccb2STzvetomir Stoyanov (VMware) 		flags &= ~TEP_FIELD_IS_ARRAY;
30969364727SSebastian Andrzej Siewior 
310*bb39ccb2STzvetomir Stoyanov (VMware) 	if (flags & TEP_FIELD_IS_DYNAMIC) {
31169364727SSebastian Andrzej Siewior 		unsigned long long tmp_val;
31269364727SSebastian Andrzej Siewior 
31359c1baeeSTzvetomir Stoyanov (VMware) 		tmp_val = tep_read_number(fmtf->event->pevent,
31469364727SSebastian Andrzej Siewior 					  data + offset, len);
31569364727SSebastian Andrzej Siewior 		offset = tmp_val;
31669364727SSebastian Andrzej Siewior 		len = offset >> 16;
31769364727SSebastian Andrzej Siewior 		offset &= 0xffff;
31869364727SSebastian Andrzej Siewior 	}
31969364727SSebastian Andrzej Siewior 
320*bb39ccb2STzvetomir Stoyanov (VMware) 	if (flags & TEP_FIELD_IS_ARRAY) {
32169364727SSebastian Andrzej Siewior 
32269364727SSebastian Andrzej Siewior 		type = bt_ctf_event_class_get_field_by_name(
32369364727SSebastian Andrzej Siewior 				event_class, name);
32469364727SSebastian Andrzej Siewior 		array_field = bt_ctf_field_create(type);
32569364727SSebastian Andrzej Siewior 		bt_ctf_field_type_put(type);
32669364727SSebastian Andrzej Siewior 		if (!array_field) {
32769364727SSebastian Andrzej Siewior 			pr_err("Failed to create array type %s\n", name);
32869364727SSebastian Andrzej Siewior 			return -1;
32969364727SSebastian Andrzej Siewior 		}
33069364727SSebastian Andrzej Siewior 
33169364727SSebastian Andrzej Siewior 		len = fmtf->size / fmtf->arraylen;
33269364727SSebastian Andrzej Siewior 		n_items = fmtf->arraylen;
33369364727SSebastian Andrzej Siewior 	} else {
33469364727SSebastian Andrzej Siewior 		n_items = 1;
33569364727SSebastian Andrzej Siewior 		array_field = NULL;
33669364727SSebastian Andrzej Siewior 	}
33769364727SSebastian Andrzej Siewior 
33869364727SSebastian Andrzej Siewior 	type = get_tracepoint_field_type(cw, fmtf);
33969364727SSebastian Andrzej Siewior 
34069364727SSebastian Andrzej Siewior 	for (i = 0; i < n_items; i++) {
341*bb39ccb2STzvetomir Stoyanov (VMware) 		if (flags & TEP_FIELD_IS_ARRAY)
34269364727SSebastian Andrzej Siewior 			field = bt_ctf_field_array_get_field(array_field, i);
34369364727SSebastian Andrzej Siewior 		else
34469364727SSebastian Andrzej Siewior 			field = bt_ctf_field_create(type);
34569364727SSebastian Andrzej Siewior 
34669364727SSebastian Andrzej Siewior 		if (!field) {
34769364727SSebastian Andrzej Siewior 			pr_err("failed to create a field %s\n", name);
34869364727SSebastian Andrzej Siewior 			return -1;
34969364727SSebastian Andrzej Siewior 		}
35069364727SSebastian Andrzej Siewior 
351*bb39ccb2STzvetomir Stoyanov (VMware) 		if (flags & TEP_FIELD_IS_STRING)
3525ea5888bSWang Nan 			ret = string_set_value(field, data + offset + i * len);
353d4ae4213SWang Nan 		else {
354d4ae4213SWang Nan 			unsigned long long value_int;
355d4ae4213SWang Nan 
35659c1baeeSTzvetomir Stoyanov (VMware) 			value_int = tep_read_number(
357d4ae4213SWang Nan 					fmtf->event->pevent,
358d4ae4213SWang Nan 					data + offset + i * len, len);
359d4ae4213SWang Nan 
360*bb39ccb2STzvetomir Stoyanov (VMware) 			if (!(flags & TEP_FIELD_IS_SIGNED))
36169364727SSebastian Andrzej Siewior 				ret = bt_ctf_field_unsigned_integer_set_value(
36269364727SSebastian Andrzej Siewior 						field, value_int);
36369364727SSebastian Andrzej Siewior 			else
36469364727SSebastian Andrzej Siewior 				ret = bt_ctf_field_signed_integer_set_value(
365d4ae4213SWang Nan 						field, adjust_signedness(value_int, len));
366d4ae4213SWang Nan 		}
367d4ae4213SWang Nan 
36869364727SSebastian Andrzej Siewior 		if (ret) {
36969364727SSebastian Andrzej Siewior 			pr_err("failed to set file value %s\n", name);
37069364727SSebastian Andrzej Siewior 			goto err_put_field;
37169364727SSebastian Andrzej Siewior 		}
372*bb39ccb2STzvetomir Stoyanov (VMware) 		if (!(flags & TEP_FIELD_IS_ARRAY)) {
37369364727SSebastian Andrzej Siewior 			ret = bt_ctf_event_set_payload(event, name, field);
37469364727SSebastian Andrzej Siewior 			if (ret) {
37569364727SSebastian Andrzej Siewior 				pr_err("failed to set payload %s\n", name);
37669364727SSebastian Andrzej Siewior 				goto err_put_field;
37769364727SSebastian Andrzej Siewior 			}
37869364727SSebastian Andrzej Siewior 		}
37969364727SSebastian Andrzej Siewior 		bt_ctf_field_put(field);
38069364727SSebastian Andrzej Siewior 	}
381*bb39ccb2STzvetomir Stoyanov (VMware) 	if (flags & TEP_FIELD_IS_ARRAY) {
38269364727SSebastian Andrzej Siewior 		ret = bt_ctf_event_set_payload(event, name, array_field);
38369364727SSebastian Andrzej Siewior 		if (ret) {
38469364727SSebastian Andrzej Siewior 			pr_err("Failed add payload array %s\n", name);
38569364727SSebastian Andrzej Siewior 			return -1;
38669364727SSebastian Andrzej Siewior 		}
38769364727SSebastian Andrzej Siewior 		bt_ctf_field_put(array_field);
38869364727SSebastian Andrzej Siewior 	}
38969364727SSebastian Andrzej Siewior 	return 0;
39069364727SSebastian Andrzej Siewior 
39169364727SSebastian Andrzej Siewior err_put_field:
39269364727SSebastian Andrzej Siewior 	bt_ctf_field_put(field);
39369364727SSebastian Andrzej Siewior 	return -1;
39469364727SSebastian Andrzej Siewior }
39569364727SSebastian Andrzej Siewior 
39669364727SSebastian Andrzej Siewior static int add_tracepoint_fields_values(struct ctf_writer *cw,
39769364727SSebastian Andrzej Siewior 					struct bt_ctf_event_class *event_class,
39869364727SSebastian Andrzej Siewior 					struct bt_ctf_event *event,
3992c92f982STzvetomir Stoyanov (VMware) 					struct tep_format_field *fields,
40069364727SSebastian Andrzej Siewior 					struct perf_sample *sample)
40169364727SSebastian Andrzej Siewior {
4022c92f982STzvetomir Stoyanov (VMware) 	struct tep_format_field *field;
40369364727SSebastian Andrzej Siewior 	int ret;
40469364727SSebastian Andrzej Siewior 
40569364727SSebastian Andrzej Siewior 	for (field = fields; field; field = field->next) {
40669364727SSebastian Andrzej Siewior 		ret = add_tracepoint_field_value(cw, event_class, event, sample,
40769364727SSebastian Andrzej Siewior 				field);
40869364727SSebastian Andrzej Siewior 		if (ret)
40969364727SSebastian Andrzej Siewior 			return -1;
41069364727SSebastian Andrzej Siewior 	}
41169364727SSebastian Andrzej Siewior 	return 0;
41269364727SSebastian Andrzej Siewior }
41369364727SSebastian Andrzej Siewior 
41469364727SSebastian Andrzej Siewior static int add_tracepoint_values(struct ctf_writer *cw,
41569364727SSebastian Andrzej Siewior 				 struct bt_ctf_event_class *event_class,
41669364727SSebastian Andrzej Siewior 				 struct bt_ctf_event *event,
41769364727SSebastian Andrzej Siewior 				 struct perf_evsel *evsel,
41869364727SSebastian Andrzej Siewior 				 struct perf_sample *sample)
41969364727SSebastian Andrzej Siewior {
4202c92f982STzvetomir Stoyanov (VMware) 	struct tep_format_field *common_fields = evsel->tp_format->format.common_fields;
4212c92f982STzvetomir Stoyanov (VMware) 	struct tep_format_field *fields        = evsel->tp_format->format.fields;
42269364727SSebastian Andrzej Siewior 	int ret;
42369364727SSebastian Andrzej Siewior 
42469364727SSebastian Andrzej Siewior 	ret = add_tracepoint_fields_values(cw, event_class, event,
42569364727SSebastian Andrzej Siewior 					   common_fields, sample);
42669364727SSebastian Andrzej Siewior 	if (!ret)
42769364727SSebastian Andrzej Siewior 		ret = add_tracepoint_fields_values(cw, event_class, event,
42869364727SSebastian Andrzej Siewior 						   fields, sample);
42969364727SSebastian Andrzej Siewior 
43069364727SSebastian Andrzej Siewior 	return ret;
43169364727SSebastian Andrzej Siewior }
43269364727SSebastian Andrzej Siewior 
4336122d57eSWang Nan static int
4346122d57eSWang Nan add_bpf_output_values(struct bt_ctf_event_class *event_class,
4356122d57eSWang Nan 		      struct bt_ctf_event *event,
4366122d57eSWang Nan 		      struct perf_sample *sample)
4376122d57eSWang Nan {
4386122d57eSWang Nan 	struct bt_ctf_field_type *len_type, *seq_type;
4396122d57eSWang Nan 	struct bt_ctf_field *len_field, *seq_field;
4406122d57eSWang Nan 	unsigned int raw_size = sample->raw_size;
4416122d57eSWang Nan 	unsigned int nr_elements = raw_size / sizeof(u32);
4426122d57eSWang Nan 	unsigned int i;
4436122d57eSWang Nan 	int ret;
4446122d57eSWang Nan 
4456122d57eSWang Nan 	if (nr_elements * sizeof(u32) != raw_size)
446f2c8852eSWang Nan 		pr_warning("Incorrect raw_size (%u) in bpf output event, skip %zu bytes\n",
4476122d57eSWang Nan 			   raw_size, nr_elements * sizeof(u32) - raw_size);
4486122d57eSWang Nan 
4496122d57eSWang Nan 	len_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_len");
4506122d57eSWang Nan 	len_field = bt_ctf_field_create(len_type);
4516122d57eSWang Nan 	if (!len_field) {
4526122d57eSWang Nan 		pr_err("failed to create 'raw_len' for bpf output event\n");
4536122d57eSWang Nan 		ret = -1;
4546122d57eSWang Nan 		goto put_len_type;
4556122d57eSWang Nan 	}
4566122d57eSWang Nan 
4576122d57eSWang Nan 	ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements);
4586122d57eSWang Nan 	if (ret) {
4596122d57eSWang Nan 		pr_err("failed to set field value for raw_len\n");
4606122d57eSWang Nan 		goto put_len_field;
4616122d57eSWang Nan 	}
4626122d57eSWang Nan 	ret = bt_ctf_event_set_payload(event, "raw_len", len_field);
4636122d57eSWang Nan 	if (ret) {
4646122d57eSWang Nan 		pr_err("failed to set payload to raw_len\n");
4656122d57eSWang Nan 		goto put_len_field;
4666122d57eSWang Nan 	}
4676122d57eSWang Nan 
4686122d57eSWang Nan 	seq_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_data");
4696122d57eSWang Nan 	seq_field = bt_ctf_field_create(seq_type);
4706122d57eSWang Nan 	if (!seq_field) {
4716122d57eSWang Nan 		pr_err("failed to create 'raw_data' for bpf output event\n");
4726122d57eSWang Nan 		ret = -1;
4736122d57eSWang Nan 		goto put_seq_type;
4746122d57eSWang Nan 	}
4756122d57eSWang Nan 
4766122d57eSWang Nan 	ret = bt_ctf_field_sequence_set_length(seq_field, len_field);
4776122d57eSWang Nan 	if (ret) {
4786122d57eSWang Nan 		pr_err("failed to set length of 'raw_data'\n");
4796122d57eSWang Nan 		goto put_seq_field;
4806122d57eSWang Nan 	}
4816122d57eSWang Nan 
4826122d57eSWang Nan 	for (i = 0; i < nr_elements; i++) {
4836122d57eSWang Nan 		struct bt_ctf_field *elem_field =
4846122d57eSWang Nan 			bt_ctf_field_sequence_get_field(seq_field, i);
4856122d57eSWang Nan 
4866122d57eSWang Nan 		ret = bt_ctf_field_unsigned_integer_set_value(elem_field,
4876122d57eSWang Nan 				((u32 *)(sample->raw_data))[i]);
4886122d57eSWang Nan 
4896122d57eSWang Nan 		bt_ctf_field_put(elem_field);
4906122d57eSWang Nan 		if (ret) {
4916122d57eSWang Nan 			pr_err("failed to set raw_data[%d]\n", i);
4926122d57eSWang Nan 			goto put_seq_field;
4936122d57eSWang Nan 		}
4946122d57eSWang Nan 	}
4956122d57eSWang Nan 
4966122d57eSWang Nan 	ret = bt_ctf_event_set_payload(event, "raw_data", seq_field);
4976122d57eSWang Nan 	if (ret)
4986122d57eSWang Nan 		pr_err("failed to set payload for raw_data\n");
4996122d57eSWang Nan 
5006122d57eSWang Nan put_seq_field:
5016122d57eSWang Nan 	bt_ctf_field_put(seq_field);
5026122d57eSWang Nan put_seq_type:
5036122d57eSWang Nan 	bt_ctf_field_type_put(seq_type);
5046122d57eSWang Nan put_len_field:
5056122d57eSWang Nan 	bt_ctf_field_put(len_field);
5066122d57eSWang Nan put_len_type:
5076122d57eSWang Nan 	bt_ctf_field_type_put(len_type);
5086122d57eSWang Nan 	return ret;
5096122d57eSWang Nan }
5106122d57eSWang Nan 
511a3073c8eSGeneviève Bastien static int
512a3073c8eSGeneviève Bastien add_callchain_output_values(struct bt_ctf_event_class *event_class,
513a3073c8eSGeneviève Bastien 		      struct bt_ctf_event *event,
514a3073c8eSGeneviève Bastien 		      struct ip_callchain *callchain)
515a3073c8eSGeneviève Bastien {
516a3073c8eSGeneviève Bastien 	struct bt_ctf_field_type *len_type, *seq_type;
517a3073c8eSGeneviève Bastien 	struct bt_ctf_field *len_field, *seq_field;
518a3073c8eSGeneviève Bastien 	unsigned int nr_elements = callchain->nr;
519a3073c8eSGeneviève Bastien 	unsigned int i;
520a3073c8eSGeneviève Bastien 	int ret;
521a3073c8eSGeneviève Bastien 
522a3073c8eSGeneviève Bastien 	len_type = bt_ctf_event_class_get_field_by_name(
523a3073c8eSGeneviève Bastien 			event_class, "perf_callchain_size");
524a3073c8eSGeneviève Bastien 	len_field = bt_ctf_field_create(len_type);
525a3073c8eSGeneviève Bastien 	if (!len_field) {
526a3073c8eSGeneviève Bastien 		pr_err("failed to create 'perf_callchain_size' for callchain output event\n");
527a3073c8eSGeneviève Bastien 		ret = -1;
528a3073c8eSGeneviève Bastien 		goto put_len_type;
529a3073c8eSGeneviève Bastien 	}
530a3073c8eSGeneviève Bastien 
531a3073c8eSGeneviève Bastien 	ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements);
532a3073c8eSGeneviève Bastien 	if (ret) {
533a3073c8eSGeneviève Bastien 		pr_err("failed to set field value for perf_callchain_size\n");
534a3073c8eSGeneviève Bastien 		goto put_len_field;
535a3073c8eSGeneviève Bastien 	}
536a3073c8eSGeneviève Bastien 	ret = bt_ctf_event_set_payload(event, "perf_callchain_size", len_field);
537a3073c8eSGeneviève Bastien 	if (ret) {
538a3073c8eSGeneviève Bastien 		pr_err("failed to set payload to perf_callchain_size\n");
539a3073c8eSGeneviève Bastien 		goto put_len_field;
540a3073c8eSGeneviève Bastien 	}
541a3073c8eSGeneviève Bastien 
542a3073c8eSGeneviève Bastien 	seq_type = bt_ctf_event_class_get_field_by_name(
543a3073c8eSGeneviève Bastien 			event_class, "perf_callchain");
544a3073c8eSGeneviève Bastien 	seq_field = bt_ctf_field_create(seq_type);
545a3073c8eSGeneviève Bastien 	if (!seq_field) {
546a3073c8eSGeneviève Bastien 		pr_err("failed to create 'perf_callchain' for callchain output event\n");
547a3073c8eSGeneviève Bastien 		ret = -1;
548a3073c8eSGeneviève Bastien 		goto put_seq_type;
549a3073c8eSGeneviève Bastien 	}
550a3073c8eSGeneviève Bastien 
551a3073c8eSGeneviève Bastien 	ret = bt_ctf_field_sequence_set_length(seq_field, len_field);
552a3073c8eSGeneviève Bastien 	if (ret) {
553a3073c8eSGeneviève Bastien 		pr_err("failed to set length of 'perf_callchain'\n");
554a3073c8eSGeneviève Bastien 		goto put_seq_field;
555a3073c8eSGeneviève Bastien 	}
556a3073c8eSGeneviève Bastien 
557a3073c8eSGeneviève Bastien 	for (i = 0; i < nr_elements; i++) {
558a3073c8eSGeneviève Bastien 		struct bt_ctf_field *elem_field =
559a3073c8eSGeneviève Bastien 			bt_ctf_field_sequence_get_field(seq_field, i);
560a3073c8eSGeneviève Bastien 
561a3073c8eSGeneviève Bastien 		ret = bt_ctf_field_unsigned_integer_set_value(elem_field,
562a3073c8eSGeneviève Bastien 				((u64 *)(callchain->ips))[i]);
563a3073c8eSGeneviève Bastien 
564a3073c8eSGeneviève Bastien 		bt_ctf_field_put(elem_field);
565a3073c8eSGeneviève Bastien 		if (ret) {
566a3073c8eSGeneviève Bastien 			pr_err("failed to set callchain[%d]\n", i);
567a3073c8eSGeneviève Bastien 			goto put_seq_field;
568a3073c8eSGeneviève Bastien 		}
569a3073c8eSGeneviève Bastien 	}
570a3073c8eSGeneviève Bastien 
571a3073c8eSGeneviève Bastien 	ret = bt_ctf_event_set_payload(event, "perf_callchain", seq_field);
572a3073c8eSGeneviève Bastien 	if (ret)
573a3073c8eSGeneviève Bastien 		pr_err("failed to set payload for raw_data\n");
574a3073c8eSGeneviève Bastien 
575a3073c8eSGeneviève Bastien put_seq_field:
576a3073c8eSGeneviève Bastien 	bt_ctf_field_put(seq_field);
577a3073c8eSGeneviève Bastien put_seq_type:
578a3073c8eSGeneviève Bastien 	bt_ctf_field_type_put(seq_type);
579a3073c8eSGeneviève Bastien put_len_field:
580a3073c8eSGeneviève Bastien 	bt_ctf_field_put(len_field);
581a3073c8eSGeneviève Bastien put_len_type:
582a3073c8eSGeneviève Bastien 	bt_ctf_field_type_put(len_type);
583a3073c8eSGeneviève Bastien 	return ret;
584a3073c8eSGeneviève Bastien }
585a3073c8eSGeneviève Bastien 
586edbe9817SJiri Olsa static int add_generic_values(struct ctf_writer *cw,
587edbe9817SJiri Olsa 			      struct bt_ctf_event *event,
588edbe9817SJiri Olsa 			      struct perf_evsel *evsel,
589edbe9817SJiri Olsa 			      struct perf_sample *sample)
590edbe9817SJiri Olsa {
591edbe9817SJiri Olsa 	u64 type = evsel->attr.sample_type;
592edbe9817SJiri Olsa 	int ret;
593edbe9817SJiri Olsa 
594edbe9817SJiri Olsa 	/*
595edbe9817SJiri Olsa 	 * missing:
596edbe9817SJiri Olsa 	 *   PERF_SAMPLE_TIME         - not needed as we have it in
597edbe9817SJiri Olsa 	 *                              ctf event header
598edbe9817SJiri Olsa 	 *   PERF_SAMPLE_READ         - TODO
599edbe9817SJiri Olsa 	 *   PERF_SAMPLE_RAW          - tracepoint fields are handled separately
600edbe9817SJiri Olsa 	 *   PERF_SAMPLE_BRANCH_STACK - TODO
601edbe9817SJiri Olsa 	 *   PERF_SAMPLE_REGS_USER    - TODO
602edbe9817SJiri Olsa 	 *   PERF_SAMPLE_STACK_USER   - TODO
603edbe9817SJiri Olsa 	 */
604edbe9817SJiri Olsa 
605edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_IP) {
60654cf776aSSebastian Andrzej Siewior 		ret = value_set_u64_hex(cw, event, "perf_ip", sample->ip);
607edbe9817SJiri Olsa 		if (ret)
608edbe9817SJiri Olsa 			return -1;
609edbe9817SJiri Olsa 	}
610edbe9817SJiri Olsa 
611edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_TID) {
61254cf776aSSebastian Andrzej Siewior 		ret = value_set_s32(cw, event, "perf_tid", sample->tid);
613edbe9817SJiri Olsa 		if (ret)
614edbe9817SJiri Olsa 			return -1;
615edbe9817SJiri Olsa 
61654cf776aSSebastian Andrzej Siewior 		ret = value_set_s32(cw, event, "perf_pid", sample->pid);
617edbe9817SJiri Olsa 		if (ret)
618edbe9817SJiri Olsa 			return -1;
619edbe9817SJiri Olsa 	}
620edbe9817SJiri Olsa 
621edbe9817SJiri Olsa 	if ((type & PERF_SAMPLE_ID) ||
622edbe9817SJiri Olsa 	    (type & PERF_SAMPLE_IDENTIFIER)) {
62354cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_id", sample->id);
624edbe9817SJiri Olsa 		if (ret)
625edbe9817SJiri Olsa 			return -1;
626edbe9817SJiri Olsa 	}
627edbe9817SJiri Olsa 
628edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_STREAM_ID) {
62954cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_stream_id", sample->stream_id);
630edbe9817SJiri Olsa 		if (ret)
631edbe9817SJiri Olsa 			return -1;
632edbe9817SJiri Olsa 	}
633edbe9817SJiri Olsa 
634edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_PERIOD) {
63554cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_period", sample->period);
636edbe9817SJiri Olsa 		if (ret)
637edbe9817SJiri Olsa 			return -1;
638edbe9817SJiri Olsa 	}
639edbe9817SJiri Olsa 
640edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_WEIGHT) {
64154cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_weight", sample->weight);
642edbe9817SJiri Olsa 		if (ret)
643edbe9817SJiri Olsa 			return -1;
644edbe9817SJiri Olsa 	}
645edbe9817SJiri Olsa 
646edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_DATA_SRC) {
64754cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_data_src",
64854cf776aSSebastian Andrzej Siewior 				sample->data_src);
649edbe9817SJiri Olsa 		if (ret)
650edbe9817SJiri Olsa 			return -1;
651edbe9817SJiri Olsa 	}
652edbe9817SJiri Olsa 
653edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_TRANSACTION) {
65454cf776aSSebastian Andrzej Siewior 		ret = value_set_u64(cw, event, "perf_transaction",
65554cf776aSSebastian Andrzej Siewior 				sample->transaction);
656edbe9817SJiri Olsa 		if (ret)
657edbe9817SJiri Olsa 			return -1;
658edbe9817SJiri Olsa 	}
659edbe9817SJiri Olsa 
660edbe9817SJiri Olsa 	return 0;
661edbe9817SJiri Olsa }
662edbe9817SJiri Olsa 
66390e129ffSSebastian Andrzej Siewior static int ctf_stream__flush(struct ctf_stream *cs)
66490e129ffSSebastian Andrzej Siewior {
66590e129ffSSebastian Andrzej Siewior 	int err = 0;
66690e129ffSSebastian Andrzej Siewior 
66790e129ffSSebastian Andrzej Siewior 	if (cs) {
66890e129ffSSebastian Andrzej Siewior 		err = bt_ctf_stream_flush(cs->stream);
66990e129ffSSebastian Andrzej Siewior 		if (err)
67090e129ffSSebastian Andrzej Siewior 			pr_err("CTF stream %d flush failed\n", cs->cpu);
67190e129ffSSebastian Andrzej Siewior 
67289e5fa88SJiri Olsa 		pr("Flush stream for cpu %d (%u samples)\n",
67389e5fa88SJiri Olsa 		   cs->cpu, cs->count);
67489e5fa88SJiri Olsa 
67589e5fa88SJiri Olsa 		cs->count = 0;
67690e129ffSSebastian Andrzej Siewior 	}
67790e129ffSSebastian Andrzej Siewior 
67890e129ffSSebastian Andrzej Siewior 	return err;
67990e129ffSSebastian Andrzej Siewior }
68090e129ffSSebastian Andrzej Siewior 
68190e129ffSSebastian Andrzej Siewior static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu)
68290e129ffSSebastian Andrzej Siewior {
68390e129ffSSebastian Andrzej Siewior 	struct ctf_stream *cs;
68490e129ffSSebastian Andrzej Siewior 	struct bt_ctf_field *pkt_ctx   = NULL;
68590e129ffSSebastian Andrzej Siewior 	struct bt_ctf_field *cpu_field = NULL;
68690e129ffSSebastian Andrzej Siewior 	struct bt_ctf_stream *stream   = NULL;
68790e129ffSSebastian Andrzej Siewior 	int ret;
68890e129ffSSebastian Andrzej Siewior 
68990e129ffSSebastian Andrzej Siewior 	cs = zalloc(sizeof(*cs));
69090e129ffSSebastian Andrzej Siewior 	if (!cs) {
69190e129ffSSebastian Andrzej Siewior 		pr_err("Failed to allocate ctf stream\n");
69290e129ffSSebastian Andrzej Siewior 		return NULL;
69390e129ffSSebastian Andrzej Siewior 	}
69490e129ffSSebastian Andrzej Siewior 
69590e129ffSSebastian Andrzej Siewior 	stream = bt_ctf_writer_create_stream(cw->writer, cw->stream_class);
69690e129ffSSebastian Andrzej Siewior 	if (!stream) {
69790e129ffSSebastian Andrzej Siewior 		pr_err("Failed to create CTF stream\n");
69890e129ffSSebastian Andrzej Siewior 		goto out;
69990e129ffSSebastian Andrzej Siewior 	}
70090e129ffSSebastian Andrzej Siewior 
70190e129ffSSebastian Andrzej Siewior 	pkt_ctx = bt_ctf_stream_get_packet_context(stream);
70290e129ffSSebastian Andrzej Siewior 	if (!pkt_ctx) {
70390e129ffSSebastian Andrzej Siewior 		pr_err("Failed to obtain packet context\n");
70490e129ffSSebastian Andrzej Siewior 		goto out;
70590e129ffSSebastian Andrzej Siewior 	}
70690e129ffSSebastian Andrzej Siewior 
70790e129ffSSebastian Andrzej Siewior 	cpu_field = bt_ctf_field_structure_get_field(pkt_ctx, "cpu_id");
70890e129ffSSebastian Andrzej Siewior 	bt_ctf_field_put(pkt_ctx);
70990e129ffSSebastian Andrzej Siewior 	if (!cpu_field) {
71090e129ffSSebastian Andrzej Siewior 		pr_err("Failed to obtain cpu field\n");
71190e129ffSSebastian Andrzej Siewior 		goto out;
71290e129ffSSebastian Andrzej Siewior 	}
71390e129ffSSebastian Andrzej Siewior 
71490e129ffSSebastian Andrzej Siewior 	ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu);
71590e129ffSSebastian Andrzej Siewior 	if (ret) {
71690e129ffSSebastian Andrzej Siewior 		pr_err("Failed to update CPU number\n");
71790e129ffSSebastian Andrzej Siewior 		goto out;
71890e129ffSSebastian Andrzej Siewior 	}
71990e129ffSSebastian Andrzej Siewior 
72090e129ffSSebastian Andrzej Siewior 	bt_ctf_field_put(cpu_field);
72190e129ffSSebastian Andrzej Siewior 
72290e129ffSSebastian Andrzej Siewior 	cs->cpu    = cpu;
72390e129ffSSebastian Andrzej Siewior 	cs->stream = stream;
72490e129ffSSebastian Andrzej Siewior 	return cs;
72590e129ffSSebastian Andrzej Siewior 
72690e129ffSSebastian Andrzej Siewior out:
72790e129ffSSebastian Andrzej Siewior 	if (cpu_field)
72890e129ffSSebastian Andrzej Siewior 		bt_ctf_field_put(cpu_field);
72990e129ffSSebastian Andrzej Siewior 	if (stream)
73090e129ffSSebastian Andrzej Siewior 		bt_ctf_stream_put(stream);
73190e129ffSSebastian Andrzej Siewior 
73290e129ffSSebastian Andrzej Siewior 	free(cs);
73390e129ffSSebastian Andrzej Siewior 	return NULL;
73490e129ffSSebastian Andrzej Siewior }
73590e129ffSSebastian Andrzej Siewior 
73690e129ffSSebastian Andrzej Siewior static void ctf_stream__delete(struct ctf_stream *cs)
73790e129ffSSebastian Andrzej Siewior {
73890e129ffSSebastian Andrzej Siewior 	if (cs) {
73990e129ffSSebastian Andrzej Siewior 		bt_ctf_stream_put(cs->stream);
74090e129ffSSebastian Andrzej Siewior 		free(cs);
74190e129ffSSebastian Andrzej Siewior 	}
74290e129ffSSebastian Andrzej Siewior }
74390e129ffSSebastian Andrzej Siewior 
74490e129ffSSebastian Andrzej Siewior static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu)
74590e129ffSSebastian Andrzej Siewior {
74690e129ffSSebastian Andrzej Siewior 	struct ctf_stream *cs = cw->stream[cpu];
74790e129ffSSebastian Andrzej Siewior 
74890e129ffSSebastian Andrzej Siewior 	if (!cs) {
74990e129ffSSebastian Andrzej Siewior 		cs = ctf_stream__create(cw, cpu);
75090e129ffSSebastian Andrzej Siewior 		cw->stream[cpu] = cs;
75190e129ffSSebastian Andrzej Siewior 	}
75290e129ffSSebastian Andrzej Siewior 
75390e129ffSSebastian Andrzej Siewior 	return cs;
75490e129ffSSebastian Andrzej Siewior }
75590e129ffSSebastian Andrzej Siewior 
75690e129ffSSebastian Andrzej Siewior static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample,
75790e129ffSSebastian Andrzej Siewior 			  struct perf_evsel *evsel)
75890e129ffSSebastian Andrzej Siewior {
75990e129ffSSebastian Andrzej Siewior 	int cpu = 0;
76090e129ffSSebastian Andrzej Siewior 
76190e129ffSSebastian Andrzej Siewior 	if (evsel->attr.sample_type & PERF_SAMPLE_CPU)
76290e129ffSSebastian Andrzej Siewior 		cpu = sample->cpu;
76390e129ffSSebastian Andrzej Siewior 
76490e129ffSSebastian Andrzej Siewior 	if (cpu > cw->stream_cnt) {
76590e129ffSSebastian Andrzej Siewior 		pr_err("Event was recorded for CPU %d, limit is at %d.\n",
76690e129ffSSebastian Andrzej Siewior 			cpu, cw->stream_cnt);
76790e129ffSSebastian Andrzej Siewior 		cpu = 0;
76890e129ffSSebastian Andrzej Siewior 	}
76990e129ffSSebastian Andrzej Siewior 
77090e129ffSSebastian Andrzej Siewior 	return cpu;
77190e129ffSSebastian Andrzej Siewior }
77290e129ffSSebastian Andrzej Siewior 
77389e5fa88SJiri Olsa #define STREAM_FLUSH_COUNT 100000
77489e5fa88SJiri Olsa 
77589e5fa88SJiri Olsa /*
77689e5fa88SJiri Olsa  * Currently we have no other way to determine the
77789e5fa88SJiri Olsa  * time for the stream flush other than keep track
77889e5fa88SJiri Olsa  * of the number of events and check it against
77989e5fa88SJiri Olsa  * threshold.
78089e5fa88SJiri Olsa  */
78189e5fa88SJiri Olsa static bool is_flush_needed(struct ctf_stream *cs)
78289e5fa88SJiri Olsa {
78389e5fa88SJiri Olsa 	return cs->count >= STREAM_FLUSH_COUNT;
78489e5fa88SJiri Olsa }
78589e5fa88SJiri Olsa 
786edbe9817SJiri Olsa static int process_sample_event(struct perf_tool *tool,
787b8f8eb84SArnaldo Carvalho de Melo 				union perf_event *_event,
788edbe9817SJiri Olsa 				struct perf_sample *sample,
789edbe9817SJiri Olsa 				struct perf_evsel *evsel,
790edbe9817SJiri Olsa 				struct machine *machine __maybe_unused)
791edbe9817SJiri Olsa {
792edbe9817SJiri Olsa 	struct convert *c = container_of(tool, struct convert, tool);
793edbe9817SJiri Olsa 	struct evsel_priv *priv = evsel->priv;
794edbe9817SJiri Olsa 	struct ctf_writer *cw = &c->writer;
79590e129ffSSebastian Andrzej Siewior 	struct ctf_stream *cs;
796edbe9817SJiri Olsa 	struct bt_ctf_event_class *event_class;
797edbe9817SJiri Olsa 	struct bt_ctf_event *event;
798edbe9817SJiri Olsa 	int ret;
799a3073c8eSGeneviève Bastien 	unsigned long type = evsel->attr.sample_type;
800edbe9817SJiri Olsa 
801edbe9817SJiri Olsa 	if (WARN_ONCE(!priv, "Failed to setup all events.\n"))
802edbe9817SJiri Olsa 		return 0;
803edbe9817SJiri Olsa 
804edbe9817SJiri Olsa 	event_class = priv->event_class;
805edbe9817SJiri Olsa 
806edbe9817SJiri Olsa 	/* update stats */
807edbe9817SJiri Olsa 	c->events_count++;
808edbe9817SJiri Olsa 	c->events_size += _event->header.size;
809edbe9817SJiri Olsa 
810edbe9817SJiri Olsa 	pr_time2(sample->time, "sample %" PRIu64 "\n", c->events_count);
811edbe9817SJiri Olsa 
812edbe9817SJiri Olsa 	event = bt_ctf_event_create(event_class);
813edbe9817SJiri Olsa 	if (!event) {
814edbe9817SJiri Olsa 		pr_err("Failed to create an CTF event\n");
815edbe9817SJiri Olsa 		return -1;
816edbe9817SJiri Olsa 	}
817edbe9817SJiri Olsa 
818edbe9817SJiri Olsa 	bt_ctf_clock_set_time(cw->clock, sample->time);
819edbe9817SJiri Olsa 
820edbe9817SJiri Olsa 	ret = add_generic_values(cw, event, evsel, sample);
821edbe9817SJiri Olsa 	if (ret)
822edbe9817SJiri Olsa 		return -1;
823edbe9817SJiri Olsa 
82469364727SSebastian Andrzej Siewior 	if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
82569364727SSebastian Andrzej Siewior 		ret = add_tracepoint_values(cw, event_class, event,
82669364727SSebastian Andrzej Siewior 					    evsel, sample);
82769364727SSebastian Andrzej Siewior 		if (ret)
82869364727SSebastian Andrzej Siewior 			return -1;
82969364727SSebastian Andrzej Siewior 	}
83069364727SSebastian Andrzej Siewior 
831a3073c8eSGeneviève Bastien 	if (type & PERF_SAMPLE_CALLCHAIN) {
832a3073c8eSGeneviève Bastien 		ret = add_callchain_output_values(event_class,
833a3073c8eSGeneviève Bastien 				event, sample->callchain);
834a3073c8eSGeneviève Bastien 		if (ret)
835a3073c8eSGeneviève Bastien 			return -1;
836a3073c8eSGeneviève Bastien 	}
837a3073c8eSGeneviève Bastien 
8386122d57eSWang Nan 	if (perf_evsel__is_bpf_output(evsel)) {
8396122d57eSWang Nan 		ret = add_bpf_output_values(event_class, event, sample);
8406122d57eSWang Nan 		if (ret)
8416122d57eSWang Nan 			return -1;
8426122d57eSWang Nan 	}
8436122d57eSWang Nan 
84490e129ffSSebastian Andrzej Siewior 	cs = ctf_stream(cw, get_sample_cpu(cw, sample, evsel));
84589e5fa88SJiri Olsa 	if (cs) {
84689e5fa88SJiri Olsa 		if (is_flush_needed(cs))
84789e5fa88SJiri Olsa 			ctf_stream__flush(cs);
84889e5fa88SJiri Olsa 
84989e5fa88SJiri Olsa 		cs->count++;
85090e129ffSSebastian Andrzej Siewior 		bt_ctf_stream_append_event(cs->stream, event);
85189e5fa88SJiri Olsa 	}
85290e129ffSSebastian Andrzej Siewior 
853edbe9817SJiri Olsa 	bt_ctf_event_put(event);
85490e129ffSSebastian Andrzej Siewior 	return cs ? 0 : -1;
855edbe9817SJiri Olsa }
856edbe9817SJiri Olsa 
857f5a08cedSWang Nan #define __NON_SAMPLE_SET_FIELD(_name, _type, _field) 	\
858f5a08cedSWang Nan do {							\
859f5a08cedSWang Nan 	ret = value_set_##_type(cw, event, #_field, _event->_name._field);\
860f5a08cedSWang Nan 	if (ret)					\
861f5a08cedSWang Nan 		return -1;				\
862f5a08cedSWang Nan } while(0)
863f5a08cedSWang Nan 
864f5a08cedSWang Nan #define __FUNC_PROCESS_NON_SAMPLE(_name, body) 	\
865f5a08cedSWang Nan static int process_##_name##_event(struct perf_tool *tool,	\
866f5a08cedSWang Nan 				   union perf_event *_event,	\
867f5a08cedSWang Nan 				   struct perf_sample *sample,	\
868f5a08cedSWang Nan 				   struct machine *machine)	\
869f5a08cedSWang Nan {								\
870f5a08cedSWang Nan 	struct convert *c = container_of(tool, struct convert, tool);\
871f5a08cedSWang Nan 	struct ctf_writer *cw = &c->writer;			\
872f5a08cedSWang Nan 	struct bt_ctf_event_class *event_class = cw->_name##_class;\
873f5a08cedSWang Nan 	struct bt_ctf_event *event;				\
874f5a08cedSWang Nan 	struct ctf_stream *cs;					\
875f5a08cedSWang Nan 	int ret;						\
876f5a08cedSWang Nan 								\
877f5a08cedSWang Nan 	c->non_sample_count++;					\
878f5a08cedSWang Nan 	c->events_size += _event->header.size;			\
879f5a08cedSWang Nan 	event = bt_ctf_event_create(event_class);		\
880f5a08cedSWang Nan 	if (!event) {						\
881f5a08cedSWang Nan 		pr_err("Failed to create an CTF event\n");	\
882f5a08cedSWang Nan 		return -1;					\
883f5a08cedSWang Nan 	}							\
884f5a08cedSWang Nan 								\
885f5a08cedSWang Nan 	bt_ctf_clock_set_time(cw->clock, sample->time);		\
886f5a08cedSWang Nan 	body							\
887f5a08cedSWang Nan 	cs = ctf_stream(cw, 0);					\
888f5a08cedSWang Nan 	if (cs) {						\
889f5a08cedSWang Nan 		if (is_flush_needed(cs))			\
890f5a08cedSWang Nan 			ctf_stream__flush(cs);			\
891f5a08cedSWang Nan 								\
892f5a08cedSWang Nan 		cs->count++;					\
893f5a08cedSWang Nan 		bt_ctf_stream_append_event(cs->stream, event);	\
894f5a08cedSWang Nan 	}							\
895f5a08cedSWang Nan 	bt_ctf_event_put(event);				\
896f5a08cedSWang Nan 								\
897f5a08cedSWang Nan 	return perf_event__process_##_name(tool, _event, sample, machine);\
898f5a08cedSWang Nan }
899f5a08cedSWang Nan 
900f5a08cedSWang Nan __FUNC_PROCESS_NON_SAMPLE(comm,
901f5a08cedSWang Nan 	__NON_SAMPLE_SET_FIELD(comm, u32, pid);
902f5a08cedSWang Nan 	__NON_SAMPLE_SET_FIELD(comm, u32, tid);
903f5a08cedSWang Nan 	__NON_SAMPLE_SET_FIELD(comm, string, comm);
904f5a08cedSWang Nan )
905ebccba3fSWang Nan __FUNC_PROCESS_NON_SAMPLE(fork,
906ebccba3fSWang Nan 	__NON_SAMPLE_SET_FIELD(fork, u32, pid);
907ebccba3fSWang Nan 	__NON_SAMPLE_SET_FIELD(fork, u32, ppid);
908ebccba3fSWang Nan 	__NON_SAMPLE_SET_FIELD(fork, u32, tid);
909ebccba3fSWang Nan 	__NON_SAMPLE_SET_FIELD(fork, u32, ptid);
910ebccba3fSWang Nan 	__NON_SAMPLE_SET_FIELD(fork, u64, time);
911ebccba3fSWang Nan )
912ebccba3fSWang Nan 
913ebccba3fSWang Nan __FUNC_PROCESS_NON_SAMPLE(exit,
914ebccba3fSWang Nan 	__NON_SAMPLE_SET_FIELD(fork, u32, pid);
915ebccba3fSWang Nan 	__NON_SAMPLE_SET_FIELD(fork, u32, ppid);
916ebccba3fSWang Nan 	__NON_SAMPLE_SET_FIELD(fork, u32, tid);
917ebccba3fSWang Nan 	__NON_SAMPLE_SET_FIELD(fork, u32, ptid);
918ebccba3fSWang Nan 	__NON_SAMPLE_SET_FIELD(fork, u64, time);
919ebccba3fSWang Nan )
920f9f6f2a9SGeneviève Bastien __FUNC_PROCESS_NON_SAMPLE(mmap,
921f9f6f2a9SGeneviève Bastien 	__NON_SAMPLE_SET_FIELD(mmap, u32, pid);
922f9f6f2a9SGeneviève Bastien 	__NON_SAMPLE_SET_FIELD(mmap, u32, tid);
923f9f6f2a9SGeneviève Bastien 	__NON_SAMPLE_SET_FIELD(mmap, u64_hex, start);
924f9f6f2a9SGeneviève Bastien 	__NON_SAMPLE_SET_FIELD(mmap, string, filename);
925f9f6f2a9SGeneviève Bastien )
926f9f6f2a9SGeneviève Bastien __FUNC_PROCESS_NON_SAMPLE(mmap2,
927f9f6f2a9SGeneviève Bastien 	__NON_SAMPLE_SET_FIELD(mmap2, u32, pid);
928f9f6f2a9SGeneviève Bastien 	__NON_SAMPLE_SET_FIELD(mmap2, u32, tid);
929f9f6f2a9SGeneviève Bastien 	__NON_SAMPLE_SET_FIELD(mmap2, u64_hex, start);
930f9f6f2a9SGeneviève Bastien 	__NON_SAMPLE_SET_FIELD(mmap2, string, filename);
931f9f6f2a9SGeneviève Bastien )
932f5a08cedSWang Nan #undef __NON_SAMPLE_SET_FIELD
933f5a08cedSWang Nan #undef __FUNC_PROCESS_NON_SAMPLE
934f5a08cedSWang Nan 
935e0a7cce5SWang Nan /* If dup < 0, add a prefix. Else, add _dupl_X suffix. */
936e0a7cce5SWang Nan static char *change_name(char *name, char *orig_name, int dup)
937e0a7cce5SWang Nan {
938e0a7cce5SWang Nan 	char *new_name = NULL;
939e0a7cce5SWang Nan 	size_t len;
940e0a7cce5SWang Nan 
941e0a7cce5SWang Nan 	if (!name)
942e0a7cce5SWang Nan 		name = orig_name;
943e0a7cce5SWang Nan 
944e0a7cce5SWang Nan 	if (dup >= 10)
945e0a7cce5SWang Nan 		goto out;
946e0a7cce5SWang Nan 	/*
947e0a7cce5SWang Nan 	 * Add '_' prefix to potential keywork.  According to
948e0a7cce5SWang Nan 	 * Mathieu Desnoyers (https://lkml.org/lkml/2015/1/23/652),
949e0a7cce5SWang Nan 	 * futher CTF spec updating may require us to use '$'.
950e0a7cce5SWang Nan 	 */
951e0a7cce5SWang Nan 	if (dup < 0)
952e0a7cce5SWang Nan 		len = strlen(name) + sizeof("_");
953e0a7cce5SWang Nan 	else
954e0a7cce5SWang Nan 		len = strlen(orig_name) + sizeof("_dupl_X");
955e0a7cce5SWang Nan 
956e0a7cce5SWang Nan 	new_name = malloc(len);
957e0a7cce5SWang Nan 	if (!new_name)
958e0a7cce5SWang Nan 		goto out;
959e0a7cce5SWang Nan 
960e0a7cce5SWang Nan 	if (dup < 0)
961e0a7cce5SWang Nan 		snprintf(new_name, len, "_%s", name);
962e0a7cce5SWang Nan 	else
963e0a7cce5SWang Nan 		snprintf(new_name, len, "%s_dupl_%d", orig_name, dup);
964e0a7cce5SWang Nan 
965e0a7cce5SWang Nan out:
966e0a7cce5SWang Nan 	if (name != orig_name)
967e0a7cce5SWang Nan 		free(name);
968e0a7cce5SWang Nan 	return new_name;
969e0a7cce5SWang Nan }
970e0a7cce5SWang Nan 
971e0a7cce5SWang Nan static int event_class_add_field(struct bt_ctf_event_class *event_class,
972e0a7cce5SWang Nan 		struct bt_ctf_field_type *type,
9732c92f982STzvetomir Stoyanov (VMware) 		struct tep_format_field *field)
974e0a7cce5SWang Nan {
975e0a7cce5SWang Nan 	struct bt_ctf_field_type *t = NULL;
976e0a7cce5SWang Nan 	char *name;
977e0a7cce5SWang Nan 	int dup = 1;
978e0a7cce5SWang Nan 	int ret;
979e0a7cce5SWang Nan 
980e0a7cce5SWang Nan 	/* alias was already assigned */
981e0a7cce5SWang Nan 	if (field->alias != field->name)
982e0a7cce5SWang Nan 		return bt_ctf_event_class_add_field(event_class, type,
983e0a7cce5SWang Nan 				(char *)field->alias);
984e0a7cce5SWang Nan 
985e0a7cce5SWang Nan 	name = field->name;
986e0a7cce5SWang Nan 
987e0a7cce5SWang Nan 	/* If 'name' is a keywork, add prefix. */
988e0a7cce5SWang Nan 	if (bt_ctf_validate_identifier(name))
989e0a7cce5SWang Nan 		name = change_name(name, field->name, -1);
990e0a7cce5SWang Nan 
991e0a7cce5SWang Nan 	if (!name) {
992e0a7cce5SWang Nan 		pr_err("Failed to fix invalid identifier.");
993e0a7cce5SWang Nan 		return -1;
994e0a7cce5SWang Nan 	}
995e0a7cce5SWang Nan 	while ((t = bt_ctf_event_class_get_field_by_name(event_class, name))) {
996e0a7cce5SWang Nan 		bt_ctf_field_type_put(t);
997e0a7cce5SWang Nan 		name = change_name(name, field->name, dup++);
998e0a7cce5SWang Nan 		if (!name) {
999e0a7cce5SWang Nan 			pr_err("Failed to create dup name for '%s'\n", field->name);
1000e0a7cce5SWang Nan 			return -1;
1001e0a7cce5SWang Nan 		}
1002e0a7cce5SWang Nan 	}
1003e0a7cce5SWang Nan 
1004e0a7cce5SWang Nan 	ret = bt_ctf_event_class_add_field(event_class, type, name);
1005e0a7cce5SWang Nan 	if (!ret)
1006e0a7cce5SWang Nan 		field->alias = name;
1007e0a7cce5SWang Nan 
1008e0a7cce5SWang Nan 	return ret;
1009e0a7cce5SWang Nan }
1010e0a7cce5SWang Nan 
101169364727SSebastian Andrzej Siewior static int add_tracepoint_fields_types(struct ctf_writer *cw,
10122c92f982STzvetomir Stoyanov (VMware) 				       struct tep_format_field *fields,
101369364727SSebastian Andrzej Siewior 				       struct bt_ctf_event_class *event_class)
101469364727SSebastian Andrzej Siewior {
10152c92f982STzvetomir Stoyanov (VMware) 	struct tep_format_field *field;
101669364727SSebastian Andrzej Siewior 	int ret;
101769364727SSebastian Andrzej Siewior 
101869364727SSebastian Andrzej Siewior 	for (field = fields; field; field = field->next) {
101969364727SSebastian Andrzej Siewior 		struct bt_ctf_field_type *type;
102069364727SSebastian Andrzej Siewior 		unsigned long flags = field->flags;
102169364727SSebastian Andrzej Siewior 
102269364727SSebastian Andrzej Siewior 		pr2("  field '%s'\n", field->name);
102369364727SSebastian Andrzej Siewior 
102469364727SSebastian Andrzej Siewior 		type = get_tracepoint_field_type(cw, field);
102569364727SSebastian Andrzej Siewior 		if (!type)
102669364727SSebastian Andrzej Siewior 			return -1;
102769364727SSebastian Andrzej Siewior 
102869364727SSebastian Andrzej Siewior 		/*
102969364727SSebastian Andrzej Siewior 		 * A string is an array of chars. For this we use the string
103069364727SSebastian Andrzej Siewior 		 * type and don't care that it is an array. What we don't
103169364727SSebastian Andrzej Siewior 		 * support is an array of strings.
103269364727SSebastian Andrzej Siewior 		 */
1033*bb39ccb2STzvetomir Stoyanov (VMware) 		if (flags & TEP_FIELD_IS_STRING)
1034*bb39ccb2STzvetomir Stoyanov (VMware) 			flags &= ~TEP_FIELD_IS_ARRAY;
103569364727SSebastian Andrzej Siewior 
1036*bb39ccb2STzvetomir Stoyanov (VMware) 		if (flags & TEP_FIELD_IS_ARRAY)
103769364727SSebastian Andrzej Siewior 			type = bt_ctf_field_type_array_create(type, field->arraylen);
103869364727SSebastian Andrzej Siewior 
1039e0a7cce5SWang Nan 		ret = event_class_add_field(event_class, type, field);
104069364727SSebastian Andrzej Siewior 
1041*bb39ccb2STzvetomir Stoyanov (VMware) 		if (flags & TEP_FIELD_IS_ARRAY)
104269364727SSebastian Andrzej Siewior 			bt_ctf_field_type_put(type);
104369364727SSebastian Andrzej Siewior 
104469364727SSebastian Andrzej Siewior 		if (ret) {
1045e0a7cce5SWang Nan 			pr_err("Failed to add field '%s': %d\n",
1046e0a7cce5SWang Nan 					field->name, ret);
104769364727SSebastian Andrzej Siewior 			return -1;
104869364727SSebastian Andrzej Siewior 		}
104969364727SSebastian Andrzej Siewior 	}
105069364727SSebastian Andrzej Siewior 
105169364727SSebastian Andrzej Siewior 	return 0;
105269364727SSebastian Andrzej Siewior }
105369364727SSebastian Andrzej Siewior 
105469364727SSebastian Andrzej Siewior static int add_tracepoint_types(struct ctf_writer *cw,
105569364727SSebastian Andrzej Siewior 				struct perf_evsel *evsel,
105669364727SSebastian Andrzej Siewior 				struct bt_ctf_event_class *class)
105769364727SSebastian Andrzej Siewior {
10582c92f982STzvetomir Stoyanov (VMware) 	struct tep_format_field *common_fields = evsel->tp_format->format.common_fields;
10592c92f982STzvetomir Stoyanov (VMware) 	struct tep_format_field *fields        = evsel->tp_format->format.fields;
106069364727SSebastian Andrzej Siewior 	int ret;
106169364727SSebastian Andrzej Siewior 
106269364727SSebastian Andrzej Siewior 	ret = add_tracepoint_fields_types(cw, common_fields, class);
106369364727SSebastian Andrzej Siewior 	if (!ret)
106469364727SSebastian Andrzej Siewior 		ret = add_tracepoint_fields_types(cw, fields, class);
106569364727SSebastian Andrzej Siewior 
106669364727SSebastian Andrzej Siewior 	return ret;
106769364727SSebastian Andrzej Siewior }
106869364727SSebastian Andrzej Siewior 
10696122d57eSWang Nan static int add_bpf_output_types(struct ctf_writer *cw,
10706122d57eSWang Nan 				struct bt_ctf_event_class *class)
10716122d57eSWang Nan {
10726122d57eSWang Nan 	struct bt_ctf_field_type *len_type = cw->data.u32;
10736122d57eSWang Nan 	struct bt_ctf_field_type *seq_base_type = cw->data.u32_hex;
10746122d57eSWang Nan 	struct bt_ctf_field_type *seq_type;
10756122d57eSWang Nan 	int ret;
10766122d57eSWang Nan 
10776122d57eSWang Nan 	ret = bt_ctf_event_class_add_field(class, len_type, "raw_len");
10786122d57eSWang Nan 	if (ret)
10796122d57eSWang Nan 		return ret;
10806122d57eSWang Nan 
10816122d57eSWang Nan 	seq_type = bt_ctf_field_type_sequence_create(seq_base_type, "raw_len");
10826122d57eSWang Nan 	if (!seq_type)
10836122d57eSWang Nan 		return -1;
10846122d57eSWang Nan 
10856122d57eSWang Nan 	return bt_ctf_event_class_add_field(class, seq_type, "raw_data");
10866122d57eSWang Nan }
10876122d57eSWang Nan 
1088edbe9817SJiri Olsa static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
1089edbe9817SJiri Olsa 			     struct bt_ctf_event_class *event_class)
1090edbe9817SJiri Olsa {
1091edbe9817SJiri Olsa 	u64 type = evsel->attr.sample_type;
1092edbe9817SJiri Olsa 
1093edbe9817SJiri Olsa 	/*
1094edbe9817SJiri Olsa 	 * missing:
1095edbe9817SJiri Olsa 	 *   PERF_SAMPLE_TIME         - not needed as we have it in
1096edbe9817SJiri Olsa 	 *                              ctf event header
1097edbe9817SJiri Olsa 	 *   PERF_SAMPLE_READ         - TODO
1098edbe9817SJiri Olsa 	 *   PERF_SAMPLE_CALLCHAIN    - TODO
10996122d57eSWang Nan 	 *   PERF_SAMPLE_RAW          - tracepoint fields and BPF output
11006122d57eSWang Nan 	 *                              are handled separately
1101edbe9817SJiri Olsa 	 *   PERF_SAMPLE_BRANCH_STACK - TODO
1102edbe9817SJiri Olsa 	 *   PERF_SAMPLE_REGS_USER    - TODO
1103edbe9817SJiri Olsa 	 *   PERF_SAMPLE_STACK_USER   - TODO
1104edbe9817SJiri Olsa 	 */
1105edbe9817SJiri Olsa 
1106edbe9817SJiri Olsa #define ADD_FIELD(cl, t, n)						\
1107edbe9817SJiri Olsa 	do {								\
1108edbe9817SJiri Olsa 		pr2("  field '%s'\n", n);				\
1109edbe9817SJiri Olsa 		if (bt_ctf_event_class_add_field(cl, t, n)) {		\
1110e0a7cce5SWang Nan 			pr_err("Failed to add field '%s';\n", n);	\
1111edbe9817SJiri Olsa 			return -1;					\
1112edbe9817SJiri Olsa 		}							\
1113edbe9817SJiri Olsa 	} while (0)
1114edbe9817SJiri Olsa 
1115edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_IP)
111654cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64_hex, "perf_ip");
1117edbe9817SJiri Olsa 
1118edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_TID) {
111954cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.s32, "perf_tid");
112054cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.s32, "perf_pid");
1121edbe9817SJiri Olsa 	}
1122edbe9817SJiri Olsa 
1123edbe9817SJiri Olsa 	if ((type & PERF_SAMPLE_ID) ||
1124edbe9817SJiri Olsa 	    (type & PERF_SAMPLE_IDENTIFIER))
112554cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_id");
1126edbe9817SJiri Olsa 
1127edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_STREAM_ID)
112854cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_stream_id");
1129edbe9817SJiri Olsa 
1130edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_PERIOD)
113154cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_period");
1132edbe9817SJiri Olsa 
1133edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_WEIGHT)
113454cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_weight");
1135edbe9817SJiri Olsa 
1136edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_DATA_SRC)
113754cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_data_src");
1138edbe9817SJiri Olsa 
1139edbe9817SJiri Olsa 	if (type & PERF_SAMPLE_TRANSACTION)
114054cf776aSSebastian Andrzej Siewior 		ADD_FIELD(event_class, cw->data.u64, "perf_transaction");
1141edbe9817SJiri Olsa 
1142a3073c8eSGeneviève Bastien 	if (type & PERF_SAMPLE_CALLCHAIN) {
1143a3073c8eSGeneviève Bastien 		ADD_FIELD(event_class, cw->data.u32, "perf_callchain_size");
1144a3073c8eSGeneviève Bastien 		ADD_FIELD(event_class,
1145a3073c8eSGeneviève Bastien 			bt_ctf_field_type_sequence_create(
1146a3073c8eSGeneviève Bastien 				cw->data.u64_hex, "perf_callchain_size"),
1147a3073c8eSGeneviève Bastien 			"perf_callchain");
1148a3073c8eSGeneviève Bastien 	}
1149a3073c8eSGeneviève Bastien 
1150edbe9817SJiri Olsa #undef ADD_FIELD
1151edbe9817SJiri Olsa 	return 0;
1152edbe9817SJiri Olsa }
1153edbe9817SJiri Olsa 
1154edbe9817SJiri Olsa static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
1155edbe9817SJiri Olsa {
1156edbe9817SJiri Olsa 	struct bt_ctf_event_class *event_class;
1157edbe9817SJiri Olsa 	struct evsel_priv *priv;
1158edbe9817SJiri Olsa 	const char *name = perf_evsel__name(evsel);
1159edbe9817SJiri Olsa 	int ret;
1160edbe9817SJiri Olsa 
1161edbe9817SJiri Olsa 	pr("Adding event '%s' (type %d)\n", name, evsel->attr.type);
1162edbe9817SJiri Olsa 
1163edbe9817SJiri Olsa 	event_class = bt_ctf_event_class_create(name);
1164edbe9817SJiri Olsa 	if (!event_class)
1165edbe9817SJiri Olsa 		return -1;
1166edbe9817SJiri Olsa 
1167edbe9817SJiri Olsa 	ret = add_generic_types(cw, evsel, event_class);
1168edbe9817SJiri Olsa 	if (ret)
1169edbe9817SJiri Olsa 		goto err;
1170edbe9817SJiri Olsa 
117169364727SSebastian Andrzej Siewior 	if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
117269364727SSebastian Andrzej Siewior 		ret = add_tracepoint_types(cw, evsel, event_class);
117369364727SSebastian Andrzej Siewior 		if (ret)
117469364727SSebastian Andrzej Siewior 			goto err;
117569364727SSebastian Andrzej Siewior 	}
117669364727SSebastian Andrzej Siewior 
11776122d57eSWang Nan 	if (perf_evsel__is_bpf_output(evsel)) {
11786122d57eSWang Nan 		ret = add_bpf_output_types(cw, event_class);
11796122d57eSWang Nan 		if (ret)
11806122d57eSWang Nan 			goto err;
11816122d57eSWang Nan 	}
11826122d57eSWang Nan 
1183edbe9817SJiri Olsa 	ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);
1184edbe9817SJiri Olsa 	if (ret) {
1185edbe9817SJiri Olsa 		pr("Failed to add event class into stream.\n");
1186edbe9817SJiri Olsa 		goto err;
1187edbe9817SJiri Olsa 	}
1188edbe9817SJiri Olsa 
1189edbe9817SJiri Olsa 	priv = malloc(sizeof(*priv));
1190edbe9817SJiri Olsa 	if (!priv)
1191edbe9817SJiri Olsa 		goto err;
1192edbe9817SJiri Olsa 
1193edbe9817SJiri Olsa 	priv->event_class = event_class;
1194edbe9817SJiri Olsa 	evsel->priv       = priv;
1195edbe9817SJiri Olsa 	return 0;
1196edbe9817SJiri Olsa 
1197edbe9817SJiri Olsa err:
1198edbe9817SJiri Olsa 	bt_ctf_event_class_put(event_class);
1199edbe9817SJiri Olsa 	pr_err("Failed to add event '%s'.\n", name);
1200edbe9817SJiri Olsa 	return -1;
1201edbe9817SJiri Olsa }
1202edbe9817SJiri Olsa 
1203edbe9817SJiri Olsa static int setup_events(struct ctf_writer *cw, struct perf_session *session)
1204edbe9817SJiri Olsa {
1205edbe9817SJiri Olsa 	struct perf_evlist *evlist = session->evlist;
1206edbe9817SJiri Olsa 	struct perf_evsel *evsel;
1207edbe9817SJiri Olsa 	int ret;
1208edbe9817SJiri Olsa 
1209e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
1210edbe9817SJiri Olsa 		ret = add_event(cw, evsel);
1211edbe9817SJiri Olsa 		if (ret)
1212edbe9817SJiri Olsa 			return ret;
1213edbe9817SJiri Olsa 	}
1214edbe9817SJiri Olsa 	return 0;
1215edbe9817SJiri Olsa }
1216edbe9817SJiri Olsa 
1217f5a08cedSWang Nan #define __NON_SAMPLE_ADD_FIELD(t, n)						\
1218f5a08cedSWang Nan 	do {							\
1219f5a08cedSWang Nan 		pr2("  field '%s'\n", #n);			\
1220f5a08cedSWang Nan 		if (bt_ctf_event_class_add_field(event_class, cw->data.t, #n)) {\
1221f5a08cedSWang Nan 			pr_err("Failed to add field '%s';\n", #n);\
1222f5a08cedSWang Nan 			return -1;				\
1223f5a08cedSWang Nan 		}						\
1224f5a08cedSWang Nan 	} while(0)
1225f5a08cedSWang Nan 
1226f5a08cedSWang Nan #define __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(_name, body) 		\
1227f5a08cedSWang Nan static int add_##_name##_event(struct ctf_writer *cw)		\
1228f5a08cedSWang Nan {								\
1229f5a08cedSWang Nan 	struct bt_ctf_event_class *event_class;			\
1230f5a08cedSWang Nan 	int ret;						\
1231f5a08cedSWang Nan 								\
1232f5a08cedSWang Nan 	pr("Adding "#_name" event\n");				\
1233f5a08cedSWang Nan 	event_class = bt_ctf_event_class_create("perf_" #_name);\
1234f5a08cedSWang Nan 	if (!event_class)					\
1235f5a08cedSWang Nan 		return -1;					\
1236f5a08cedSWang Nan 	body							\
1237f5a08cedSWang Nan 								\
1238f5a08cedSWang Nan 	ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);\
1239f5a08cedSWang Nan 	if (ret) {						\
1240f5a08cedSWang Nan 		pr("Failed to add event class '"#_name"' into stream.\n");\
1241f5a08cedSWang Nan 		return ret;					\
1242f5a08cedSWang Nan 	}							\
1243f5a08cedSWang Nan 								\
1244f5a08cedSWang Nan 	cw->_name##_class = event_class;			\
1245f5a08cedSWang Nan 	bt_ctf_event_class_put(event_class);			\
1246f5a08cedSWang Nan 	return 0;						\
1247f5a08cedSWang Nan }
1248f5a08cedSWang Nan 
1249f5a08cedSWang Nan __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(comm,
1250f5a08cedSWang Nan 	__NON_SAMPLE_ADD_FIELD(u32, pid);
1251f5a08cedSWang Nan 	__NON_SAMPLE_ADD_FIELD(u32, tid);
1252f5a08cedSWang Nan 	__NON_SAMPLE_ADD_FIELD(string, comm);
1253f5a08cedSWang Nan )
1254f5a08cedSWang Nan 
1255ebccba3fSWang Nan __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(fork,
1256ebccba3fSWang Nan 	__NON_SAMPLE_ADD_FIELD(u32, pid);
1257ebccba3fSWang Nan 	__NON_SAMPLE_ADD_FIELD(u32, ppid);
1258ebccba3fSWang Nan 	__NON_SAMPLE_ADD_FIELD(u32, tid);
1259ebccba3fSWang Nan 	__NON_SAMPLE_ADD_FIELD(u32, ptid);
1260ebccba3fSWang Nan 	__NON_SAMPLE_ADD_FIELD(u64, time);
1261ebccba3fSWang Nan )
1262ebccba3fSWang Nan 
1263ebccba3fSWang Nan __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(exit,
1264ebccba3fSWang Nan 	__NON_SAMPLE_ADD_FIELD(u32, pid);
1265ebccba3fSWang Nan 	__NON_SAMPLE_ADD_FIELD(u32, ppid);
1266ebccba3fSWang Nan 	__NON_SAMPLE_ADD_FIELD(u32, tid);
1267ebccba3fSWang Nan 	__NON_SAMPLE_ADD_FIELD(u32, ptid);
1268ebccba3fSWang Nan 	__NON_SAMPLE_ADD_FIELD(u64, time);
1269ebccba3fSWang Nan )
1270ebccba3fSWang Nan 
1271f9f6f2a9SGeneviève Bastien __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(mmap,
1272f9f6f2a9SGeneviève Bastien 	__NON_SAMPLE_ADD_FIELD(u32, pid);
1273f9f6f2a9SGeneviève Bastien 	__NON_SAMPLE_ADD_FIELD(u32, tid);
1274f9f6f2a9SGeneviève Bastien 	__NON_SAMPLE_ADD_FIELD(u64_hex, start);
1275f9f6f2a9SGeneviève Bastien 	__NON_SAMPLE_ADD_FIELD(string, filename);
1276f9f6f2a9SGeneviève Bastien )
1277f9f6f2a9SGeneviève Bastien 
1278f9f6f2a9SGeneviève Bastien __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(mmap2,
1279f9f6f2a9SGeneviève Bastien 	__NON_SAMPLE_ADD_FIELD(u32, pid);
1280f9f6f2a9SGeneviève Bastien 	__NON_SAMPLE_ADD_FIELD(u32, tid);
1281f9f6f2a9SGeneviève Bastien 	__NON_SAMPLE_ADD_FIELD(u64_hex, start);
1282f9f6f2a9SGeneviève Bastien 	__NON_SAMPLE_ADD_FIELD(string, filename);
1283f9f6f2a9SGeneviève Bastien )
1284f5a08cedSWang Nan #undef __NON_SAMPLE_ADD_FIELD
1285f5a08cedSWang Nan #undef __FUNC_ADD_NON_SAMPLE_EVENT_CLASS
1286f5a08cedSWang Nan 
1287f5a08cedSWang Nan static int setup_non_sample_events(struct ctf_writer *cw,
1288f5a08cedSWang Nan 				   struct perf_session *session __maybe_unused)
1289f5a08cedSWang Nan {
1290f5a08cedSWang Nan 	int ret;
1291f5a08cedSWang Nan 
1292f5a08cedSWang Nan 	ret = add_comm_event(cw);
1293f5a08cedSWang Nan 	if (ret)
1294f5a08cedSWang Nan 		return ret;
1295ebccba3fSWang Nan 	ret = add_exit_event(cw);
1296ebccba3fSWang Nan 	if (ret)
1297ebccba3fSWang Nan 		return ret;
1298ebccba3fSWang Nan 	ret = add_fork_event(cw);
1299ebccba3fSWang Nan 	if (ret)
1300ebccba3fSWang Nan 		return ret;
1301f9f6f2a9SGeneviève Bastien 	ret = add_mmap_event(cw);
1302f9f6f2a9SGeneviève Bastien 	if (ret)
1303f9f6f2a9SGeneviève Bastien 		return ret;
1304f9f6f2a9SGeneviève Bastien 	ret = add_mmap2_event(cw);
1305f9f6f2a9SGeneviève Bastien 	if (ret)
1306f9f6f2a9SGeneviève Bastien 		return ret;
1307f5a08cedSWang Nan 	return 0;
1308f5a08cedSWang Nan }
1309f5a08cedSWang Nan 
13105141d735SWang Nan static void cleanup_events(struct perf_session *session)
13115141d735SWang Nan {
13125141d735SWang Nan 	struct perf_evlist *evlist = session->evlist;
13135141d735SWang Nan 	struct perf_evsel *evsel;
13145141d735SWang Nan 
1315e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
13165141d735SWang Nan 		struct evsel_priv *priv;
13175141d735SWang Nan 
13185141d735SWang Nan 		priv = evsel->priv;
13195141d735SWang Nan 		bt_ctf_event_class_put(priv->event_class);
13205141d735SWang Nan 		zfree(&evsel->priv);
13215141d735SWang Nan 	}
13225141d735SWang Nan 
13235141d735SWang Nan 	perf_evlist__delete(evlist);
13245141d735SWang Nan 	session->evlist = NULL;
13255141d735SWang Nan }
13265141d735SWang Nan 
132790e129ffSSebastian Andrzej Siewior static int setup_streams(struct ctf_writer *cw, struct perf_session *session)
132890e129ffSSebastian Andrzej Siewior {
132990e129ffSSebastian Andrzej Siewior 	struct ctf_stream **stream;
133090e129ffSSebastian Andrzej Siewior 	struct perf_header *ph = &session->header;
133190e129ffSSebastian Andrzej Siewior 	int ncpus;
133290e129ffSSebastian Andrzej Siewior 
133390e129ffSSebastian Andrzej Siewior 	/*
133490e129ffSSebastian Andrzej Siewior 	 * Try to get the number of cpus used in the data file,
133590e129ffSSebastian Andrzej Siewior 	 * if not present fallback to the MAX_CPUS.
133690e129ffSSebastian Andrzej Siewior 	 */
133790e129ffSSebastian Andrzej Siewior 	ncpus = ph->env.nr_cpus_avail ?: MAX_CPUS;
133890e129ffSSebastian Andrzej Siewior 
133990e129ffSSebastian Andrzej Siewior 	stream = zalloc(sizeof(*stream) * ncpus);
134090e129ffSSebastian Andrzej Siewior 	if (!stream) {
134190e129ffSSebastian Andrzej Siewior 		pr_err("Failed to allocate streams.\n");
134290e129ffSSebastian Andrzej Siewior 		return -ENOMEM;
134390e129ffSSebastian Andrzej Siewior 	}
134490e129ffSSebastian Andrzej Siewior 
134590e129ffSSebastian Andrzej Siewior 	cw->stream     = stream;
134690e129ffSSebastian Andrzej Siewior 	cw->stream_cnt = ncpus;
134790e129ffSSebastian Andrzej Siewior 	return 0;
134890e129ffSSebastian Andrzej Siewior }
134990e129ffSSebastian Andrzej Siewior 
135090e129ffSSebastian Andrzej Siewior static void free_streams(struct ctf_writer *cw)
135190e129ffSSebastian Andrzej Siewior {
135290e129ffSSebastian Andrzej Siewior 	int cpu;
135390e129ffSSebastian Andrzej Siewior 
135490e129ffSSebastian Andrzej Siewior 	for (cpu = 0; cpu < cw->stream_cnt; cpu++)
135590e129ffSSebastian Andrzej Siewior 		ctf_stream__delete(cw->stream[cpu]);
135690e129ffSSebastian Andrzej Siewior 
135790e129ffSSebastian Andrzej Siewior 	free(cw->stream);
135890e129ffSSebastian Andrzej Siewior }
135990e129ffSSebastian Andrzej Siewior 
1360edbe9817SJiri Olsa static int ctf_writer__setup_env(struct ctf_writer *cw,
1361edbe9817SJiri Olsa 				 struct perf_session *session)
1362edbe9817SJiri Olsa {
1363edbe9817SJiri Olsa 	struct perf_header *header = &session->header;
1364edbe9817SJiri Olsa 	struct bt_ctf_writer *writer = cw->writer;
1365edbe9817SJiri Olsa 
1366edbe9817SJiri Olsa #define ADD(__n, __v)							\
1367edbe9817SJiri Olsa do {									\
1368edbe9817SJiri Olsa 	if (bt_ctf_writer_add_environment_field(writer, __n, __v))	\
1369edbe9817SJiri Olsa 		return -1;						\
1370edbe9817SJiri Olsa } while (0)
1371edbe9817SJiri Olsa 
1372edbe9817SJiri Olsa 	ADD("host",    header->env.hostname);
1373edbe9817SJiri Olsa 	ADD("sysname", "Linux");
1374edbe9817SJiri Olsa 	ADD("release", header->env.os_release);
1375edbe9817SJiri Olsa 	ADD("version", header->env.version);
1376edbe9817SJiri Olsa 	ADD("machine", header->env.arch);
1377edbe9817SJiri Olsa 	ADD("domain", "kernel");
1378edbe9817SJiri Olsa 	ADD("tracer_name", "perf");
1379edbe9817SJiri Olsa 
1380edbe9817SJiri Olsa #undef ADD
1381edbe9817SJiri Olsa 	return 0;
1382edbe9817SJiri Olsa }
1383edbe9817SJiri Olsa 
1384edbe9817SJiri Olsa static int ctf_writer__setup_clock(struct ctf_writer *cw)
1385edbe9817SJiri Olsa {
1386edbe9817SJiri Olsa 	struct bt_ctf_clock *clock = cw->clock;
1387edbe9817SJiri Olsa 
1388edbe9817SJiri Olsa 	bt_ctf_clock_set_description(clock, "perf clock");
1389edbe9817SJiri Olsa 
1390edbe9817SJiri Olsa #define SET(__n, __v)				\
1391edbe9817SJiri Olsa do {						\
1392edbe9817SJiri Olsa 	if (bt_ctf_clock_set_##__n(clock, __v))	\
1393edbe9817SJiri Olsa 		return -1;			\
1394edbe9817SJiri Olsa } while (0)
1395edbe9817SJiri Olsa 
1396edbe9817SJiri Olsa 	SET(frequency,   1000000000);
1397edbe9817SJiri Olsa 	SET(offset_s,    0);
1398edbe9817SJiri Olsa 	SET(offset,      0);
1399edbe9817SJiri Olsa 	SET(precision,   10);
1400edbe9817SJiri Olsa 	SET(is_absolute, 0);
1401edbe9817SJiri Olsa 
1402edbe9817SJiri Olsa #undef SET
1403edbe9817SJiri Olsa 	return 0;
1404edbe9817SJiri Olsa }
1405edbe9817SJiri Olsa 
1406edbe9817SJiri Olsa static struct bt_ctf_field_type *create_int_type(int size, bool sign, bool hex)
1407edbe9817SJiri Olsa {
1408edbe9817SJiri Olsa 	struct bt_ctf_field_type *type;
1409edbe9817SJiri Olsa 
1410edbe9817SJiri Olsa 	type = bt_ctf_field_type_integer_create(size);
1411edbe9817SJiri Olsa 	if (!type)
1412edbe9817SJiri Olsa 		return NULL;
1413edbe9817SJiri Olsa 
1414edbe9817SJiri Olsa 	if (sign &&
1415edbe9817SJiri Olsa 	    bt_ctf_field_type_integer_set_signed(type, 1))
1416edbe9817SJiri Olsa 		goto err;
1417edbe9817SJiri Olsa 
1418edbe9817SJiri Olsa 	if (hex &&
1419edbe9817SJiri Olsa 	    bt_ctf_field_type_integer_set_base(type, BT_CTF_INTEGER_BASE_HEXADECIMAL))
1420edbe9817SJiri Olsa 		goto err;
1421edbe9817SJiri Olsa 
1422f8dd2d5fSWang Nan #if __BYTE_ORDER == __BIG_ENDIAN
1423f8dd2d5fSWang Nan 	bt_ctf_field_type_set_byte_order(type, BT_CTF_BYTE_ORDER_BIG_ENDIAN);
1424f8dd2d5fSWang Nan #else
1425f8dd2d5fSWang Nan 	bt_ctf_field_type_set_byte_order(type, BT_CTF_BYTE_ORDER_LITTLE_ENDIAN);
1426f8dd2d5fSWang Nan #endif
1427f8dd2d5fSWang Nan 
1428edbe9817SJiri Olsa 	pr2("Created type: INTEGER %d-bit %ssigned %s\n",
1429edbe9817SJiri Olsa 	    size, sign ? "un" : "", hex ? "hex" : "");
1430edbe9817SJiri Olsa 	return type;
1431edbe9817SJiri Olsa 
1432edbe9817SJiri Olsa err:
1433edbe9817SJiri Olsa 	bt_ctf_field_type_put(type);
1434edbe9817SJiri Olsa 	return NULL;
1435edbe9817SJiri Olsa }
1436edbe9817SJiri Olsa 
1437edbe9817SJiri Olsa static void ctf_writer__cleanup_data(struct ctf_writer *cw)
1438edbe9817SJiri Olsa {
1439edbe9817SJiri Olsa 	unsigned int i;
1440edbe9817SJiri Olsa 
1441edbe9817SJiri Olsa 	for (i = 0; i < ARRAY_SIZE(cw->data.array); i++)
1442edbe9817SJiri Olsa 		bt_ctf_field_type_put(cw->data.array[i]);
1443edbe9817SJiri Olsa }
1444edbe9817SJiri Olsa 
1445edbe9817SJiri Olsa static int ctf_writer__init_data(struct ctf_writer *cw)
1446edbe9817SJiri Olsa {
1447edbe9817SJiri Olsa #define CREATE_INT_TYPE(type, size, sign, hex)		\
1448edbe9817SJiri Olsa do {							\
1449edbe9817SJiri Olsa 	(type) = create_int_type(size, sign, hex);	\
1450edbe9817SJiri Olsa 	if (!(type))					\
1451edbe9817SJiri Olsa 		goto err;				\
1452edbe9817SJiri Olsa } while (0)
1453edbe9817SJiri Olsa 
1454edbe9817SJiri Olsa 	CREATE_INT_TYPE(cw->data.s64, 64, true,  false);
1455edbe9817SJiri Olsa 	CREATE_INT_TYPE(cw->data.u64, 64, false, false);
1456edbe9817SJiri Olsa 	CREATE_INT_TYPE(cw->data.s32, 32, true,  false);
1457edbe9817SJiri Olsa 	CREATE_INT_TYPE(cw->data.u32, 32, false, false);
145826812d46SWang Nan 	CREATE_INT_TYPE(cw->data.u32_hex, 32, false, true);
1459edbe9817SJiri Olsa 	CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true);
1460edbe9817SJiri Olsa 
1461edbe9817SJiri Olsa 	cw->data.string  = bt_ctf_field_type_string_create();
1462edbe9817SJiri Olsa 	if (cw->data.string)
1463edbe9817SJiri Olsa 		return 0;
1464edbe9817SJiri Olsa 
1465edbe9817SJiri Olsa err:
1466edbe9817SJiri Olsa 	ctf_writer__cleanup_data(cw);
1467edbe9817SJiri Olsa 	pr_err("Failed to create data types.\n");
1468edbe9817SJiri Olsa 	return -1;
1469edbe9817SJiri Olsa }
1470edbe9817SJiri Olsa 
1471edbe9817SJiri Olsa static void ctf_writer__cleanup(struct ctf_writer *cw)
1472edbe9817SJiri Olsa {
1473edbe9817SJiri Olsa 	ctf_writer__cleanup_data(cw);
1474edbe9817SJiri Olsa 
1475edbe9817SJiri Olsa 	bt_ctf_clock_put(cw->clock);
147690e129ffSSebastian Andrzej Siewior 	free_streams(cw);
1477edbe9817SJiri Olsa 	bt_ctf_stream_class_put(cw->stream_class);
1478edbe9817SJiri Olsa 	bt_ctf_writer_put(cw->writer);
1479edbe9817SJiri Olsa 
1480edbe9817SJiri Olsa 	/* and NULL all the pointers */
1481edbe9817SJiri Olsa 	memset(cw, 0, sizeof(*cw));
1482edbe9817SJiri Olsa }
1483edbe9817SJiri Olsa 
1484edbe9817SJiri Olsa static int ctf_writer__init(struct ctf_writer *cw, const char *path)
1485edbe9817SJiri Olsa {
1486edbe9817SJiri Olsa 	struct bt_ctf_writer		*writer;
1487edbe9817SJiri Olsa 	struct bt_ctf_stream_class	*stream_class;
1488edbe9817SJiri Olsa 	struct bt_ctf_clock		*clock;
148990e129ffSSebastian Andrzej Siewior 	struct bt_ctf_field_type	*pkt_ctx_type;
149090e129ffSSebastian Andrzej Siewior 	int				ret;
1491edbe9817SJiri Olsa 
1492edbe9817SJiri Olsa 	/* CTF writer */
1493edbe9817SJiri Olsa 	writer = bt_ctf_writer_create(path);
1494edbe9817SJiri Olsa 	if (!writer)
1495edbe9817SJiri Olsa 		goto err;
1496edbe9817SJiri Olsa 
1497edbe9817SJiri Olsa 	cw->writer = writer;
1498edbe9817SJiri Olsa 
1499edbe9817SJiri Olsa 	/* CTF clock */
1500edbe9817SJiri Olsa 	clock = bt_ctf_clock_create("perf_clock");
1501edbe9817SJiri Olsa 	if (!clock) {
1502edbe9817SJiri Olsa 		pr("Failed to create CTF clock.\n");
1503edbe9817SJiri Olsa 		goto err_cleanup;
1504edbe9817SJiri Olsa 	}
1505edbe9817SJiri Olsa 
1506edbe9817SJiri Olsa 	cw->clock = clock;
1507edbe9817SJiri Olsa 
1508edbe9817SJiri Olsa 	if (ctf_writer__setup_clock(cw)) {
1509edbe9817SJiri Olsa 		pr("Failed to setup CTF clock.\n");
1510edbe9817SJiri Olsa 		goto err_cleanup;
1511edbe9817SJiri Olsa 	}
1512edbe9817SJiri Olsa 
1513edbe9817SJiri Olsa 	/* CTF stream class */
1514edbe9817SJiri Olsa 	stream_class = bt_ctf_stream_class_create("perf_stream");
1515edbe9817SJiri Olsa 	if (!stream_class) {
1516edbe9817SJiri Olsa 		pr("Failed to create CTF stream class.\n");
1517edbe9817SJiri Olsa 		goto err_cleanup;
1518edbe9817SJiri Olsa 	}
1519edbe9817SJiri Olsa 
1520edbe9817SJiri Olsa 	cw->stream_class = stream_class;
1521edbe9817SJiri Olsa 
1522edbe9817SJiri Olsa 	/* CTF clock stream setup */
1523edbe9817SJiri Olsa 	if (bt_ctf_stream_class_set_clock(stream_class, clock)) {
1524edbe9817SJiri Olsa 		pr("Failed to assign CTF clock to stream class.\n");
1525edbe9817SJiri Olsa 		goto err_cleanup;
1526edbe9817SJiri Olsa 	}
1527edbe9817SJiri Olsa 
1528edbe9817SJiri Olsa 	if (ctf_writer__init_data(cw))
1529edbe9817SJiri Olsa 		goto err_cleanup;
1530edbe9817SJiri Olsa 
153190e129ffSSebastian Andrzej Siewior 	/* Add cpu_id for packet context */
153290e129ffSSebastian Andrzej Siewior 	pkt_ctx_type = bt_ctf_stream_class_get_packet_context_type(stream_class);
153390e129ffSSebastian Andrzej Siewior 	if (!pkt_ctx_type)
1534edbe9817SJiri Olsa 		goto err_cleanup;
1535edbe9817SJiri Olsa 
153690e129ffSSebastian Andrzej Siewior 	ret = bt_ctf_field_type_structure_add_field(pkt_ctx_type, cw->data.u32, "cpu_id");
153790e129ffSSebastian Andrzej Siewior 	bt_ctf_field_type_put(pkt_ctx_type);
153890e129ffSSebastian Andrzej Siewior 	if (ret)
153990e129ffSSebastian Andrzej Siewior 		goto err_cleanup;
1540edbe9817SJiri Olsa 
1541edbe9817SJiri Olsa 	/* CTF clock writer setup */
1542edbe9817SJiri Olsa 	if (bt_ctf_writer_add_clock(writer, clock)) {
1543edbe9817SJiri Olsa 		pr("Failed to assign CTF clock to writer.\n");
1544edbe9817SJiri Olsa 		goto err_cleanup;
1545edbe9817SJiri Olsa 	}
1546edbe9817SJiri Olsa 
1547edbe9817SJiri Olsa 	return 0;
1548edbe9817SJiri Olsa 
1549edbe9817SJiri Olsa err_cleanup:
1550edbe9817SJiri Olsa 	ctf_writer__cleanup(cw);
1551edbe9817SJiri Olsa err:
1552edbe9817SJiri Olsa 	pr_err("Failed to setup CTF writer.\n");
1553edbe9817SJiri Olsa 	return -1;
1554edbe9817SJiri Olsa }
1555edbe9817SJiri Olsa 
155690e129ffSSebastian Andrzej Siewior static int ctf_writer__flush_streams(struct ctf_writer *cw)
155790e129ffSSebastian Andrzej Siewior {
155890e129ffSSebastian Andrzej Siewior 	int cpu, ret = 0;
155990e129ffSSebastian Andrzej Siewior 
156090e129ffSSebastian Andrzej Siewior 	for (cpu = 0; cpu < cw->stream_cnt && !ret; cpu++)
156190e129ffSSebastian Andrzej Siewior 		ret = ctf_stream__flush(cw->stream[cpu]);
156290e129ffSSebastian Andrzej Siewior 
156390e129ffSSebastian Andrzej Siewior 	return ret;
156490e129ffSSebastian Andrzej Siewior }
156590e129ffSSebastian Andrzej Siewior 
15668fa46753SJiri Olsa static int convert__config(const char *var, const char *value, void *cb)
15678fa46753SJiri Olsa {
15688fa46753SJiri Olsa 	struct convert *c = cb;
15698fa46753SJiri Olsa 
157025ce4bb8SArnaldo Carvalho de Melo 	if (!strcmp(var, "convert.queue-size"))
157125ce4bb8SArnaldo Carvalho de Melo 		return perf_config_u64(&c->queue_size, var, value);
15728fa46753SJiri Olsa 
1573b8cbb349SWang Nan 	return 0;
15748fa46753SJiri Olsa }
15758fa46753SJiri Olsa 
15763275f68eSWang Nan int bt_convert__perf2ctf(const char *input, const char *path,
15773275f68eSWang Nan 			 struct perf_data_convert_opts *opts)
1578edbe9817SJiri Olsa {
1579edbe9817SJiri Olsa 	struct perf_session *session;
15808ceb41d7SJiri Olsa 	struct perf_data data = {
1581c04c859fSJérémie Galarneau 		.file      = { .path = input, .fd = -1 },
1582edbe9817SJiri Olsa 		.mode      = PERF_DATA_MODE_READ,
15833275f68eSWang Nan 		.force     = opts->force,
1584edbe9817SJiri Olsa 	};
1585edbe9817SJiri Olsa 	struct convert c = {
1586edbe9817SJiri Olsa 		.tool = {
1587edbe9817SJiri Olsa 			.sample          = process_sample_event,
1588edbe9817SJiri Olsa 			.mmap            = perf_event__process_mmap,
1589edbe9817SJiri Olsa 			.mmap2           = perf_event__process_mmap2,
1590edbe9817SJiri Olsa 			.comm            = perf_event__process_comm,
1591edbe9817SJiri Olsa 			.exit            = perf_event__process_exit,
1592edbe9817SJiri Olsa 			.fork            = perf_event__process_fork,
1593edbe9817SJiri Olsa 			.lost            = perf_event__process_lost,
1594edbe9817SJiri Olsa 			.tracing_data    = perf_event__process_tracing_data,
1595edbe9817SJiri Olsa 			.build_id        = perf_event__process_build_id,
1596f3b3614aSHari Bathini 			.namespaces      = perf_event__process_namespaces,
1597edbe9817SJiri Olsa 			.ordered_events  = true,
1598edbe9817SJiri Olsa 			.ordering_requires_timestamps = true,
1599edbe9817SJiri Olsa 		},
1600edbe9817SJiri Olsa 	};
1601edbe9817SJiri Olsa 	struct ctf_writer *cw = &c.writer;
1602ecc4c561SArnaldo Carvalho de Melo 	int err;
1603edbe9817SJiri Olsa 
1604ebccba3fSWang Nan 	if (opts->all) {
1605f5a08cedSWang Nan 		c.tool.comm = process_comm_event;
1606ebccba3fSWang Nan 		c.tool.exit = process_exit_event;
1607ebccba3fSWang Nan 		c.tool.fork = process_fork_event;
1608f9f6f2a9SGeneviève Bastien 		c.tool.mmap = process_mmap_event;
1609f9f6f2a9SGeneviève Bastien 		c.tool.mmap2 = process_mmap2_event;
1610ebccba3fSWang Nan 	}
1611f5a08cedSWang Nan 
1612ecc4c561SArnaldo Carvalho de Melo 	err = perf_config(convert__config, &c);
1613ecc4c561SArnaldo Carvalho de Melo 	if (err)
1614ecc4c561SArnaldo Carvalho de Melo 		return err;
16158fa46753SJiri Olsa 
1616edbe9817SJiri Olsa 	/* CTF writer */
1617edbe9817SJiri Olsa 	if (ctf_writer__init(cw, path))
1618edbe9817SJiri Olsa 		return -1;
1619edbe9817SJiri Olsa 
1620ecc4c561SArnaldo Carvalho de Melo 	err = -1;
1621edbe9817SJiri Olsa 	/* perf.data session */
16228ceb41d7SJiri Olsa 	session = perf_session__new(&data, 0, &c.tool);
1623edbe9817SJiri Olsa 	if (!session)
1624edbe9817SJiri Olsa 		goto free_writer;
1625edbe9817SJiri Olsa 
16268fa46753SJiri Olsa 	if (c.queue_size) {
16278fa46753SJiri Olsa 		ordered_events__set_alloc_size(&session->ordered_events,
16288fa46753SJiri Olsa 					       c.queue_size);
16298fa46753SJiri Olsa 	}
16308fa46753SJiri Olsa 
1631edbe9817SJiri Olsa 	/* CTF writer env/clock setup  */
1632edbe9817SJiri Olsa 	if (ctf_writer__setup_env(cw, session))
1633edbe9817SJiri Olsa 		goto free_session;
1634edbe9817SJiri Olsa 
1635edbe9817SJiri Olsa 	/* CTF events setup */
1636edbe9817SJiri Olsa 	if (setup_events(cw, session))
1637edbe9817SJiri Olsa 		goto free_session;
1638edbe9817SJiri Olsa 
1639f5a08cedSWang Nan 	if (opts->all && setup_non_sample_events(cw, session))
1640f5a08cedSWang Nan 		goto free_session;
1641f5a08cedSWang Nan 
164290e129ffSSebastian Andrzej Siewior 	if (setup_streams(cw, session))
164390e129ffSSebastian Andrzej Siewior 		goto free_session;
164490e129ffSSebastian Andrzej Siewior 
1645b7b61cbeSArnaldo Carvalho de Melo 	err = perf_session__process_events(session);
1646edbe9817SJiri Olsa 	if (!err)
164790e129ffSSebastian Andrzej Siewior 		err = ctf_writer__flush_streams(cw);
1648c2141055SHe Kuang 	else
1649c2141055SHe Kuang 		pr_err("Error during conversion.\n");
1650edbe9817SJiri Olsa 
1651edbe9817SJiri Olsa 	fprintf(stderr,
1652edbe9817SJiri Olsa 		"[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
1653eae8ad80SJiri Olsa 		data.file.path, path);
1654edbe9817SJiri Olsa 
1655edbe9817SJiri Olsa 	fprintf(stderr,
16568ee4c46cSWang Nan 		"[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
1657edbe9817SJiri Olsa 		(double) c.events_size / 1024.0 / 1024.0,
1658edbe9817SJiri Olsa 		c.events_count);
1659edbe9817SJiri Olsa 
16608ee4c46cSWang Nan 	if (!c.non_sample_count)
16618ee4c46cSWang Nan 		fprintf(stderr, ") ]\n");
16628ee4c46cSWang Nan 	else
16638ee4c46cSWang Nan 		fprintf(stderr, ", %" PRIu64 " non-samples) ]\n", c.non_sample_count);
16648ee4c46cSWang Nan 
16655141d735SWang Nan 	cleanup_events(session);
1666c2141055SHe Kuang 	perf_session__delete(session);
1667c2141055SHe Kuang 	ctf_writer__cleanup(cw);
1668c2141055SHe Kuang 
1669c2141055SHe Kuang 	return err;
1670c2141055SHe Kuang 
1671edbe9817SJiri Olsa free_session:
1672edbe9817SJiri Olsa 	perf_session__delete(session);
1673edbe9817SJiri Olsa free_writer:
1674edbe9817SJiri Olsa 	ctf_writer__cleanup(cw);
1675c2141055SHe Kuang 	pr_err("Error during conversion setup.\n");
1676edbe9817SJiri Olsa 	return err;
1677edbe9817SJiri Olsa }
1678