191007045SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2edbe9817SJiri Olsa /*
3edbe9817SJiri Olsa * CTF writing support via babeltrace.
4edbe9817SJiri Olsa *
5edbe9817SJiri Olsa * Copyright (C) 2014, Jiri Olsa <jolsa@redhat.com>
6edbe9817SJiri Olsa * Copyright (C) 2014, Sebastian Andrzej Siewior <bigeasy@linutronix.de>
7edbe9817SJiri Olsa */
8edbe9817SJiri Olsa
9a43783aeSArnaldo Carvalho de Melo #include <errno.h>
10fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
11edbe9817SJiri Olsa #include <linux/compiler.h>
12877a7a11SArnaldo Carvalho de Melo #include <linux/kernel.h>
137f7c536fSArnaldo Carvalho de Melo #include <linux/zalloc.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 "asm/bug.h"
23d0713d4cSNicholas Fraser #include "data-convert.h"
24edbe9817SJiri Olsa #include "session.h"
25edbe9817SJiri Olsa #include "debug.h"
26edbe9817SJiri Olsa #include "tool.h"
27edbe9817SJiri Olsa #include "evlist.h"
28edbe9817SJiri Olsa #include "evsel.h"
29edbe9817SJiri Olsa #include "machine.h"
30f6c12a00SJiri Olsa #include "config.h"
313052ba56SArnaldo Carvalho de Melo #include <linux/ctype.h>
326ef81c55SMamatha Inamdar #include <linux/err.h>
3388371c58SJiri Olsa #include <linux/time64.h>
3488371c58SJiri Olsa #include "util.h"
3588371c58SJiri Olsa #include "clockid.h"
369823147dSArnaldo Carvalho de Melo #include "util/sample.h"
37edbe9817SJiri Olsa
38378ef0f5SIan Rogers #ifdef HAVE_LIBTRACEEVENT
39378ef0f5SIan Rogers #include <traceevent/event-parse.h>
40378ef0f5SIan Rogers #endif
41378ef0f5SIan Rogers
42edbe9817SJiri Olsa #define pr_N(n, fmt, ...) \
43edbe9817SJiri Olsa eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
44edbe9817SJiri Olsa
45edbe9817SJiri Olsa #define pr(fmt, ...) pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
46edbe9817SJiri Olsa #define pr2(fmt, ...) pr_N(2, pr_fmt(fmt), ##__VA_ARGS__)
47edbe9817SJiri Olsa
48edbe9817SJiri Olsa #define pr_time2(t, fmt, ...) pr_time_N(2, debug_data_convert, t, pr_fmt(fmt), ##__VA_ARGS__)
49edbe9817SJiri Olsa
50edbe9817SJiri Olsa struct evsel_priv {
51edbe9817SJiri Olsa struct bt_ctf_event_class *event_class;
52edbe9817SJiri Olsa };
53edbe9817SJiri Olsa
5490e129ffSSebastian Andrzej Siewior #define MAX_CPUS 4096
5590e129ffSSebastian Andrzej Siewior
5690e129ffSSebastian Andrzej Siewior struct ctf_stream {
5790e129ffSSebastian Andrzej Siewior struct bt_ctf_stream *stream;
5890e129ffSSebastian Andrzej Siewior int cpu;
5989e5fa88SJiri Olsa u32 count;
6090e129ffSSebastian Andrzej Siewior };
6190e129ffSSebastian Andrzej Siewior
62edbe9817SJiri Olsa struct ctf_writer {
63edbe9817SJiri Olsa /* writer primitives */
64edbe9817SJiri Olsa struct bt_ctf_writer *writer;
6590e129ffSSebastian Andrzej Siewior struct ctf_stream **stream;
6690e129ffSSebastian Andrzej Siewior int stream_cnt;
67edbe9817SJiri Olsa struct bt_ctf_stream_class *stream_class;
68edbe9817SJiri Olsa struct bt_ctf_clock *clock;
69edbe9817SJiri Olsa
70edbe9817SJiri Olsa /* data types */
71edbe9817SJiri Olsa union {
72edbe9817SJiri Olsa struct {
73edbe9817SJiri Olsa struct bt_ctf_field_type *s64;
74edbe9817SJiri Olsa struct bt_ctf_field_type *u64;
75edbe9817SJiri Olsa struct bt_ctf_field_type *s32;
76edbe9817SJiri Olsa struct bt_ctf_field_type *u32;
77edbe9817SJiri Olsa struct bt_ctf_field_type *string;
7826812d46SWang Nan struct bt_ctf_field_type *u32_hex;
79edbe9817SJiri Olsa struct bt_ctf_field_type *u64_hex;
80edbe9817SJiri Olsa };
81edbe9817SJiri Olsa struct bt_ctf_field_type *array[6];
82edbe9817SJiri Olsa } data;
83f5a08cedSWang Nan struct bt_ctf_event_class *comm_class;
84ebccba3fSWang Nan struct bt_ctf_event_class *exit_class;
85ebccba3fSWang Nan struct bt_ctf_event_class *fork_class;
86f9f6f2a9SGeneviève Bastien struct bt_ctf_event_class *mmap_class;
87f9f6f2a9SGeneviève Bastien struct bt_ctf_event_class *mmap2_class;
88edbe9817SJiri Olsa };
89edbe9817SJiri Olsa
90edbe9817SJiri Olsa struct convert {
91edbe9817SJiri Olsa struct perf_tool tool;
92edbe9817SJiri Olsa struct ctf_writer writer;
93edbe9817SJiri Olsa
94edbe9817SJiri Olsa u64 events_size;
95edbe9817SJiri Olsa u64 events_count;
968ee4c46cSWang Nan u64 non_sample_count;
978fa46753SJiri Olsa
988fa46753SJiri Olsa /* Ordered events configured queue size. */
998fa46753SJiri Olsa u64 queue_size;
100edbe9817SJiri Olsa };
101edbe9817SJiri Olsa
value_set(struct bt_ctf_field_type * type,struct bt_ctf_event * event,const char * name,u64 val)102edbe9817SJiri Olsa static int value_set(struct bt_ctf_field_type *type,
103edbe9817SJiri Olsa struct bt_ctf_event *event,
104edbe9817SJiri Olsa const char *name, u64 val)
105edbe9817SJiri Olsa {
106edbe9817SJiri Olsa struct bt_ctf_field *field;
107edbe9817SJiri Olsa bool sign = bt_ctf_field_type_integer_get_signed(type);
108edbe9817SJiri Olsa int ret;
109edbe9817SJiri Olsa
110edbe9817SJiri Olsa field = bt_ctf_field_create(type);
111edbe9817SJiri Olsa if (!field) {
112edbe9817SJiri Olsa pr_err("failed to create a field %s\n", name);
113edbe9817SJiri Olsa return -1;
114edbe9817SJiri Olsa }
115edbe9817SJiri Olsa
116edbe9817SJiri Olsa if (sign) {
117edbe9817SJiri Olsa ret = bt_ctf_field_signed_integer_set_value(field, val);
118edbe9817SJiri Olsa if (ret) {
119edbe9817SJiri Olsa pr_err("failed to set field value %s\n", name);
120edbe9817SJiri Olsa goto err;
121edbe9817SJiri Olsa }
122edbe9817SJiri Olsa } else {
123edbe9817SJiri Olsa ret = bt_ctf_field_unsigned_integer_set_value(field, val);
124edbe9817SJiri Olsa if (ret) {
125edbe9817SJiri Olsa pr_err("failed to set field value %s\n", name);
126edbe9817SJiri Olsa goto err;
127edbe9817SJiri Olsa }
128edbe9817SJiri Olsa }
129edbe9817SJiri Olsa
130edbe9817SJiri Olsa ret = bt_ctf_event_set_payload(event, name, field);
131edbe9817SJiri Olsa if (ret) {
132edbe9817SJiri Olsa pr_err("failed to set payload %s\n", name);
133edbe9817SJiri Olsa goto err;
134edbe9817SJiri Olsa }
135edbe9817SJiri Olsa
136edbe9817SJiri Olsa pr2(" SET [%s = %" PRIu64 "]\n", name, val);
137edbe9817SJiri Olsa
138edbe9817SJiri Olsa err:
139edbe9817SJiri Olsa bt_ctf_field_put(field);
140edbe9817SJiri Olsa return ret;
141edbe9817SJiri Olsa }
142edbe9817SJiri Olsa
143edbe9817SJiri Olsa #define __FUNC_VALUE_SET(_name, _val_type) \
144edbe9817SJiri Olsa static __maybe_unused int value_set_##_name(struct ctf_writer *cw, \
145edbe9817SJiri Olsa struct bt_ctf_event *event, \
146edbe9817SJiri Olsa const char *name, \
147edbe9817SJiri Olsa _val_type val) \
148edbe9817SJiri Olsa { \
149edbe9817SJiri Olsa struct bt_ctf_field_type *type = cw->data._name; \
150edbe9817SJiri Olsa return value_set(type, event, name, (u64) val); \
151edbe9817SJiri Olsa }
152edbe9817SJiri Olsa
153edbe9817SJiri Olsa #define FUNC_VALUE_SET(_name) __FUNC_VALUE_SET(_name, _name)
154edbe9817SJiri Olsa
155edbe9817SJiri Olsa FUNC_VALUE_SET(s32)
156edbe9817SJiri Olsa FUNC_VALUE_SET(u32)
157edbe9817SJiri Olsa FUNC_VALUE_SET(s64)
158edbe9817SJiri Olsa FUNC_VALUE_SET(u64)
159edbe9817SJiri Olsa __FUNC_VALUE_SET(u64_hex, u64)
160edbe9817SJiri Olsa
161069ee5c4SWang Nan static int string_set_value(struct bt_ctf_field *field, const char *string);
162069ee5c4SWang Nan static __maybe_unused int
value_set_string(struct ctf_writer * cw,struct bt_ctf_event * event,const char * name,const char * string)163069ee5c4SWang Nan value_set_string(struct ctf_writer *cw, struct bt_ctf_event *event,
164069ee5c4SWang Nan const char *name, const char *string)
165069ee5c4SWang Nan {
166069ee5c4SWang Nan struct bt_ctf_field_type *type = cw->data.string;
167069ee5c4SWang Nan struct bt_ctf_field *field;
168069ee5c4SWang Nan int ret = 0;
169069ee5c4SWang Nan
170069ee5c4SWang Nan field = bt_ctf_field_create(type);
171069ee5c4SWang Nan if (!field) {
172069ee5c4SWang Nan pr_err("failed to create a field %s\n", name);
173069ee5c4SWang Nan return -1;
174069ee5c4SWang Nan }
175069ee5c4SWang Nan
176069ee5c4SWang Nan ret = string_set_value(field, string);
177069ee5c4SWang Nan if (ret) {
178069ee5c4SWang Nan pr_err("failed to set value %s\n", name);
179069ee5c4SWang Nan goto err_put_field;
180069ee5c4SWang Nan }
181069ee5c4SWang Nan
182069ee5c4SWang Nan ret = bt_ctf_event_set_payload(event, name, field);
183069ee5c4SWang Nan if (ret)
184069ee5c4SWang Nan pr_err("failed to set payload %s\n", name);
185069ee5c4SWang Nan
186069ee5c4SWang Nan err_put_field:
187069ee5c4SWang Nan bt_ctf_field_put(field);
188069ee5c4SWang Nan return ret;
189069ee5c4SWang Nan }
190069ee5c4SWang Nan
19169364727SSebastian Andrzej Siewior static struct bt_ctf_field_type*
get_tracepoint_field_type(struct ctf_writer * cw,struct tep_format_field * field)1922c92f982STzvetomir Stoyanov (VMware) get_tracepoint_field_type(struct ctf_writer *cw, struct tep_format_field *field)
19369364727SSebastian Andrzej Siewior {
19469364727SSebastian Andrzej Siewior unsigned long flags = field->flags;
19569364727SSebastian Andrzej Siewior
196bb39ccb2STzvetomir Stoyanov (VMware) if (flags & TEP_FIELD_IS_STRING)
19769364727SSebastian Andrzej Siewior return cw->data.string;
19869364727SSebastian Andrzej Siewior
199bb39ccb2STzvetomir Stoyanov (VMware) if (!(flags & TEP_FIELD_IS_SIGNED)) {
20069364727SSebastian Andrzej Siewior /* unsigned long are mostly pointers */
201bb39ccb2STzvetomir Stoyanov (VMware) if (flags & TEP_FIELD_IS_LONG || flags & TEP_FIELD_IS_POINTER)
20269364727SSebastian Andrzej Siewior return cw->data.u64_hex;
20369364727SSebastian Andrzej Siewior }
20469364727SSebastian Andrzej Siewior
205bb39ccb2STzvetomir Stoyanov (VMware) if (flags & TEP_FIELD_IS_SIGNED) {
20669364727SSebastian Andrzej Siewior if (field->size == 8)
20769364727SSebastian Andrzej Siewior return cw->data.s64;
20869364727SSebastian Andrzej Siewior else
20969364727SSebastian Andrzej Siewior return cw->data.s32;
21069364727SSebastian Andrzej Siewior }
21169364727SSebastian Andrzej Siewior
21269364727SSebastian Andrzej Siewior if (field->size == 8)
21369364727SSebastian Andrzej Siewior return cw->data.u64;
21469364727SSebastian Andrzej Siewior else
21569364727SSebastian Andrzej Siewior return cw->data.u32;
21669364727SSebastian Andrzej Siewior }
21769364727SSebastian Andrzej Siewior
adjust_signedness(unsigned long long value_int,int size)218d4ae4213SWang Nan static unsigned long long adjust_signedness(unsigned long long value_int, int size)
219d4ae4213SWang Nan {
220d4ae4213SWang Nan unsigned long long value_mask;
221d4ae4213SWang Nan
222d4ae4213SWang Nan /*
223d4ae4213SWang Nan * value_mask = (1 << (size * 8 - 1)) - 1.
224d4ae4213SWang Nan * Directly set value_mask for code readers.
225d4ae4213SWang Nan */
226d4ae4213SWang Nan switch (size) {
227d4ae4213SWang Nan case 1:
228d4ae4213SWang Nan value_mask = 0x7fULL;
229d4ae4213SWang Nan break;
230d4ae4213SWang Nan case 2:
231d4ae4213SWang Nan value_mask = 0x7fffULL;
232d4ae4213SWang Nan break;
233d4ae4213SWang Nan case 4:
234d4ae4213SWang Nan value_mask = 0x7fffffffULL;
235d4ae4213SWang Nan break;
236d4ae4213SWang Nan case 8:
237d4ae4213SWang Nan /*
238d4ae4213SWang Nan * For 64 bit value, return it self. There is no need
239d4ae4213SWang Nan * to fill high bit.
240d4ae4213SWang Nan */
241d4ae4213SWang Nan /* Fall through */
242d4ae4213SWang Nan default:
243d4ae4213SWang Nan /* BUG! */
244d4ae4213SWang Nan return value_int;
245d4ae4213SWang Nan }
246d4ae4213SWang Nan
247d4ae4213SWang Nan /* If it is a positive value, don't adjust. */
248d4ae4213SWang Nan if ((value_int & (~0ULL - value_mask)) == 0)
249d4ae4213SWang Nan return value_int;
250d4ae4213SWang Nan
251d4ae4213SWang Nan /* Fill upper part of value_int with 1 to make it a negative long long. */
252d4ae4213SWang Nan return (value_int & value_mask) | ~value_mask;
253d4ae4213SWang Nan }
254d4ae4213SWang Nan
string_set_value(struct bt_ctf_field * field,const char * string)2555ea5888bSWang Nan static int string_set_value(struct bt_ctf_field *field, const char *string)
2565ea5888bSWang Nan {
2575ea5888bSWang Nan char *buffer = NULL;
2585ea5888bSWang Nan size_t len = strlen(string), i, p;
2595ea5888bSWang Nan int err;
2605ea5888bSWang Nan
2615ea5888bSWang Nan for (i = p = 0; i < len; i++, p++) {
2625ea5888bSWang Nan if (isprint(string[i])) {
2635ea5888bSWang Nan if (!buffer)
2645ea5888bSWang Nan continue;
2655ea5888bSWang Nan buffer[p] = string[i];
2665ea5888bSWang Nan } else {
2675ea5888bSWang Nan char numstr[5];
2685ea5888bSWang Nan
2695ea5888bSWang Nan snprintf(numstr, sizeof(numstr), "\\x%02x",
2705ea5888bSWang Nan (unsigned int)(string[i]) & 0xff);
2715ea5888bSWang Nan
2725ea5888bSWang Nan if (!buffer) {
2735ea5888bSWang Nan buffer = zalloc(i + (len - i) * 4 + 2);
2745ea5888bSWang Nan if (!buffer) {
2755ea5888bSWang Nan pr_err("failed to set unprintable string '%s'\n", string);
2765ea5888bSWang Nan return bt_ctf_field_string_set_value(field, "UNPRINTABLE-STRING");
2775ea5888bSWang Nan }
2785ea5888bSWang Nan if (i > 0)
2795ea5888bSWang Nan strncpy(buffer, string, i);
2805ea5888bSWang Nan }
28197acec7dSShawn Landden memcpy(buffer + p, numstr, 4);
2825ea5888bSWang Nan p += 3;
2835ea5888bSWang Nan }
2845ea5888bSWang Nan }
2855ea5888bSWang Nan
2865ea5888bSWang Nan if (!buffer)
2875ea5888bSWang Nan return bt_ctf_field_string_set_value(field, string);
2885ea5888bSWang Nan err = bt_ctf_field_string_set_value(field, buffer);
2895ea5888bSWang Nan free(buffer);
2905ea5888bSWang Nan return err;
2915ea5888bSWang Nan }
2925ea5888bSWang Nan
add_tracepoint_field_value(struct ctf_writer * cw,struct bt_ctf_event_class * event_class,struct bt_ctf_event * event,struct perf_sample * sample,struct tep_format_field * fmtf)29369364727SSebastian Andrzej Siewior static int add_tracepoint_field_value(struct ctf_writer *cw,
29469364727SSebastian Andrzej Siewior struct bt_ctf_event_class *event_class,
29569364727SSebastian Andrzej Siewior struct bt_ctf_event *event,
29669364727SSebastian Andrzej Siewior struct perf_sample *sample,
2972c92f982STzvetomir Stoyanov (VMware) struct tep_format_field *fmtf)
29869364727SSebastian Andrzej Siewior {
29969364727SSebastian Andrzej Siewior struct bt_ctf_field_type *type;
30069364727SSebastian Andrzej Siewior struct bt_ctf_field *array_field;
30169364727SSebastian Andrzej Siewior struct bt_ctf_field *field;
30269364727SSebastian Andrzej Siewior const char *name = fmtf->name;
30369364727SSebastian Andrzej Siewior void *data = sample->raw_data;
30469364727SSebastian Andrzej Siewior unsigned long flags = fmtf->flags;
30569364727SSebastian Andrzej Siewior unsigned int n_items;
30669364727SSebastian Andrzej Siewior unsigned int i;
30769364727SSebastian Andrzej Siewior unsigned int offset;
30869364727SSebastian Andrzej Siewior unsigned int len;
30969364727SSebastian Andrzej Siewior int ret;
31069364727SSebastian Andrzej Siewior
311e0a7cce5SWang Nan name = fmtf->alias;
31269364727SSebastian Andrzej Siewior offset = fmtf->offset;
31369364727SSebastian Andrzej Siewior len = fmtf->size;
314bb39ccb2STzvetomir Stoyanov (VMware) if (flags & TEP_FIELD_IS_STRING)
315bb39ccb2STzvetomir Stoyanov (VMware) flags &= ~TEP_FIELD_IS_ARRAY;
31669364727SSebastian Andrzej Siewior
317bb39ccb2STzvetomir Stoyanov (VMware) if (flags & TEP_FIELD_IS_DYNAMIC) {
31869364727SSebastian Andrzej Siewior unsigned long long tmp_val;
31969364727SSebastian Andrzej Siewior
32069769ce1STzvetomir Stoyanov tmp_val = tep_read_number(fmtf->event->tep,
32169364727SSebastian Andrzej Siewior data + offset, len);
32269364727SSebastian Andrzej Siewior offset = tmp_val;
32369364727SSebastian Andrzej Siewior len = offset >> 16;
32469364727SSebastian Andrzej Siewior offset &= 0xffff;
325*1634bad3SIan Rogers if (tep_field_is_relative(flags))
3267c689c83SMasami Hiramatsu offset += fmtf->offset + fmtf->size;
32769364727SSebastian Andrzej Siewior }
32869364727SSebastian Andrzej Siewior
329bb39ccb2STzvetomir Stoyanov (VMware) if (flags & TEP_FIELD_IS_ARRAY) {
33069364727SSebastian Andrzej Siewior
33169364727SSebastian Andrzej Siewior type = bt_ctf_event_class_get_field_by_name(
33269364727SSebastian Andrzej Siewior event_class, name);
33369364727SSebastian Andrzej Siewior array_field = bt_ctf_field_create(type);
33469364727SSebastian Andrzej Siewior bt_ctf_field_type_put(type);
33569364727SSebastian Andrzej Siewior if (!array_field) {
33669364727SSebastian Andrzej Siewior pr_err("Failed to create array type %s\n", name);
33769364727SSebastian Andrzej Siewior return -1;
33869364727SSebastian Andrzej Siewior }
33969364727SSebastian Andrzej Siewior
34069364727SSebastian Andrzej Siewior len = fmtf->size / fmtf->arraylen;
34169364727SSebastian Andrzej Siewior n_items = fmtf->arraylen;
34269364727SSebastian Andrzej Siewior } else {
34369364727SSebastian Andrzej Siewior n_items = 1;
34469364727SSebastian Andrzej Siewior array_field = NULL;
34569364727SSebastian Andrzej Siewior }
34669364727SSebastian Andrzej Siewior
34769364727SSebastian Andrzej Siewior type = get_tracepoint_field_type(cw, fmtf);
34869364727SSebastian Andrzej Siewior
34969364727SSebastian Andrzej Siewior for (i = 0; i < n_items; i++) {
350bb39ccb2STzvetomir Stoyanov (VMware) if (flags & TEP_FIELD_IS_ARRAY)
35169364727SSebastian Andrzej Siewior field = bt_ctf_field_array_get_field(array_field, i);
35269364727SSebastian Andrzej Siewior else
35369364727SSebastian Andrzej Siewior field = bt_ctf_field_create(type);
35469364727SSebastian Andrzej Siewior
35569364727SSebastian Andrzej Siewior if (!field) {
35669364727SSebastian Andrzej Siewior pr_err("failed to create a field %s\n", name);
35769364727SSebastian Andrzej Siewior return -1;
35869364727SSebastian Andrzej Siewior }
35969364727SSebastian Andrzej Siewior
360bb39ccb2STzvetomir Stoyanov (VMware) if (flags & TEP_FIELD_IS_STRING)
3615ea5888bSWang Nan ret = string_set_value(field, data + offset + i * len);
362d4ae4213SWang Nan else {
363d4ae4213SWang Nan unsigned long long value_int;
364d4ae4213SWang Nan
36559c1baeeSTzvetomir Stoyanov (VMware) value_int = tep_read_number(
36669769ce1STzvetomir Stoyanov fmtf->event->tep,
367d4ae4213SWang Nan data + offset + i * len, len);
368d4ae4213SWang Nan
369bb39ccb2STzvetomir Stoyanov (VMware) if (!(flags & TEP_FIELD_IS_SIGNED))
37069364727SSebastian Andrzej Siewior ret = bt_ctf_field_unsigned_integer_set_value(
37169364727SSebastian Andrzej Siewior field, value_int);
37269364727SSebastian Andrzej Siewior else
37369364727SSebastian Andrzej Siewior ret = bt_ctf_field_signed_integer_set_value(
374d4ae4213SWang Nan field, adjust_signedness(value_int, len));
375d4ae4213SWang Nan }
376d4ae4213SWang Nan
37769364727SSebastian Andrzej Siewior if (ret) {
37869364727SSebastian Andrzej Siewior pr_err("failed to set file value %s\n", name);
37969364727SSebastian Andrzej Siewior goto err_put_field;
38069364727SSebastian Andrzej Siewior }
381bb39ccb2STzvetomir Stoyanov (VMware) if (!(flags & TEP_FIELD_IS_ARRAY)) {
38269364727SSebastian Andrzej Siewior ret = bt_ctf_event_set_payload(event, name, field);
38369364727SSebastian Andrzej Siewior if (ret) {
38469364727SSebastian Andrzej Siewior pr_err("failed to set payload %s\n", name);
38569364727SSebastian Andrzej Siewior goto err_put_field;
38669364727SSebastian Andrzej Siewior }
38769364727SSebastian Andrzej Siewior }
38869364727SSebastian Andrzej Siewior bt_ctf_field_put(field);
38969364727SSebastian Andrzej Siewior }
390bb39ccb2STzvetomir Stoyanov (VMware) if (flags & TEP_FIELD_IS_ARRAY) {
39169364727SSebastian Andrzej Siewior ret = bt_ctf_event_set_payload(event, name, array_field);
39269364727SSebastian Andrzej Siewior if (ret) {
39369364727SSebastian Andrzej Siewior pr_err("Failed add payload array %s\n", name);
39469364727SSebastian Andrzej Siewior return -1;
39569364727SSebastian Andrzej Siewior }
39669364727SSebastian Andrzej Siewior bt_ctf_field_put(array_field);
39769364727SSebastian Andrzej Siewior }
39869364727SSebastian Andrzej Siewior return 0;
39969364727SSebastian Andrzej Siewior
40069364727SSebastian Andrzej Siewior err_put_field:
40169364727SSebastian Andrzej Siewior bt_ctf_field_put(field);
40269364727SSebastian Andrzej Siewior return -1;
40369364727SSebastian Andrzej Siewior }
40469364727SSebastian Andrzej Siewior
add_tracepoint_fields_values(struct ctf_writer * cw,struct bt_ctf_event_class * event_class,struct bt_ctf_event * event,struct tep_format_field * fields,struct perf_sample * sample)40569364727SSebastian Andrzej Siewior static int add_tracepoint_fields_values(struct ctf_writer *cw,
40669364727SSebastian Andrzej Siewior struct bt_ctf_event_class *event_class,
40769364727SSebastian Andrzej Siewior struct bt_ctf_event *event,
4082c92f982STzvetomir Stoyanov (VMware) struct tep_format_field *fields,
40969364727SSebastian Andrzej Siewior struct perf_sample *sample)
41069364727SSebastian Andrzej Siewior {
4112c92f982STzvetomir Stoyanov (VMware) struct tep_format_field *field;
41269364727SSebastian Andrzej Siewior int ret;
41369364727SSebastian Andrzej Siewior
41469364727SSebastian Andrzej Siewior for (field = fields; field; field = field->next) {
41569364727SSebastian Andrzej Siewior ret = add_tracepoint_field_value(cw, event_class, event, sample,
41669364727SSebastian Andrzej Siewior field);
41769364727SSebastian Andrzej Siewior if (ret)
41869364727SSebastian Andrzej Siewior return -1;
41969364727SSebastian Andrzej Siewior }
42069364727SSebastian Andrzej Siewior return 0;
42169364727SSebastian Andrzej Siewior }
42269364727SSebastian Andrzej Siewior
add_tracepoint_values(struct ctf_writer * cw,struct bt_ctf_event_class * event_class,struct bt_ctf_event * event,struct evsel * evsel,struct perf_sample * sample)42369364727SSebastian Andrzej Siewior static int add_tracepoint_values(struct ctf_writer *cw,
42469364727SSebastian Andrzej Siewior struct bt_ctf_event_class *event_class,
42569364727SSebastian Andrzej Siewior struct bt_ctf_event *event,
42632dcd021SJiri Olsa struct evsel *evsel,
42769364727SSebastian Andrzej Siewior struct perf_sample *sample)
42869364727SSebastian Andrzej Siewior {
4292c92f982STzvetomir Stoyanov (VMware) struct tep_format_field *common_fields = evsel->tp_format->format.common_fields;
4302c92f982STzvetomir Stoyanov (VMware) struct tep_format_field *fields = evsel->tp_format->format.fields;
43169364727SSebastian Andrzej Siewior int ret;
43269364727SSebastian Andrzej Siewior
43369364727SSebastian Andrzej Siewior ret = add_tracepoint_fields_values(cw, event_class, event,
43469364727SSebastian Andrzej Siewior common_fields, sample);
43569364727SSebastian Andrzej Siewior if (!ret)
43669364727SSebastian Andrzej Siewior ret = add_tracepoint_fields_values(cw, event_class, event,
43769364727SSebastian Andrzej Siewior fields, sample);
43869364727SSebastian Andrzej Siewior
43969364727SSebastian Andrzej Siewior return ret;
44069364727SSebastian Andrzej Siewior }
44169364727SSebastian Andrzej Siewior
4426122d57eSWang Nan static int
add_bpf_output_values(struct bt_ctf_event_class * event_class,struct bt_ctf_event * event,struct perf_sample * sample)4436122d57eSWang Nan add_bpf_output_values(struct bt_ctf_event_class *event_class,
4446122d57eSWang Nan struct bt_ctf_event *event,
4456122d57eSWang Nan struct perf_sample *sample)
4466122d57eSWang Nan {
4476122d57eSWang Nan struct bt_ctf_field_type *len_type, *seq_type;
4486122d57eSWang Nan struct bt_ctf_field *len_field, *seq_field;
4496122d57eSWang Nan unsigned int raw_size = sample->raw_size;
4506122d57eSWang Nan unsigned int nr_elements = raw_size / sizeof(u32);
4516122d57eSWang Nan unsigned int i;
4526122d57eSWang Nan int ret;
4536122d57eSWang Nan
4546122d57eSWang Nan if (nr_elements * sizeof(u32) != raw_size)
455f2c8852eSWang Nan pr_warning("Incorrect raw_size (%u) in bpf output event, skip %zu bytes\n",
4566122d57eSWang Nan raw_size, nr_elements * sizeof(u32) - raw_size);
4576122d57eSWang Nan
4586122d57eSWang Nan len_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_len");
4596122d57eSWang Nan len_field = bt_ctf_field_create(len_type);
4606122d57eSWang Nan if (!len_field) {
4616122d57eSWang Nan pr_err("failed to create 'raw_len' for bpf output event\n");
4626122d57eSWang Nan ret = -1;
4636122d57eSWang Nan goto put_len_type;
4646122d57eSWang Nan }
4656122d57eSWang Nan
4666122d57eSWang Nan ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements);
4676122d57eSWang Nan if (ret) {
4686122d57eSWang Nan pr_err("failed to set field value for raw_len\n");
4696122d57eSWang Nan goto put_len_field;
4706122d57eSWang Nan }
4716122d57eSWang Nan ret = bt_ctf_event_set_payload(event, "raw_len", len_field);
4726122d57eSWang Nan if (ret) {
4736122d57eSWang Nan pr_err("failed to set payload to raw_len\n");
4746122d57eSWang Nan goto put_len_field;
4756122d57eSWang Nan }
4766122d57eSWang Nan
4776122d57eSWang Nan seq_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_data");
4786122d57eSWang Nan seq_field = bt_ctf_field_create(seq_type);
4796122d57eSWang Nan if (!seq_field) {
4806122d57eSWang Nan pr_err("failed to create 'raw_data' for bpf output event\n");
4816122d57eSWang Nan ret = -1;
4826122d57eSWang Nan goto put_seq_type;
4836122d57eSWang Nan }
4846122d57eSWang Nan
4856122d57eSWang Nan ret = bt_ctf_field_sequence_set_length(seq_field, len_field);
4866122d57eSWang Nan if (ret) {
4876122d57eSWang Nan pr_err("failed to set length of 'raw_data'\n");
4886122d57eSWang Nan goto put_seq_field;
4896122d57eSWang Nan }
4906122d57eSWang Nan
4916122d57eSWang Nan for (i = 0; i < nr_elements; i++) {
4926122d57eSWang Nan struct bt_ctf_field *elem_field =
4936122d57eSWang Nan bt_ctf_field_sequence_get_field(seq_field, i);
4946122d57eSWang Nan
4956122d57eSWang Nan ret = bt_ctf_field_unsigned_integer_set_value(elem_field,
4966122d57eSWang Nan ((u32 *)(sample->raw_data))[i]);
4976122d57eSWang Nan
4986122d57eSWang Nan bt_ctf_field_put(elem_field);
4996122d57eSWang Nan if (ret) {
5006122d57eSWang Nan pr_err("failed to set raw_data[%d]\n", i);
5016122d57eSWang Nan goto put_seq_field;
5026122d57eSWang Nan }
5036122d57eSWang Nan }
5046122d57eSWang Nan
5056122d57eSWang Nan ret = bt_ctf_event_set_payload(event, "raw_data", seq_field);
5066122d57eSWang Nan if (ret)
5076122d57eSWang Nan pr_err("failed to set payload for raw_data\n");
5086122d57eSWang Nan
5096122d57eSWang Nan put_seq_field:
5106122d57eSWang Nan bt_ctf_field_put(seq_field);
5116122d57eSWang Nan put_seq_type:
5126122d57eSWang Nan bt_ctf_field_type_put(seq_type);
5136122d57eSWang Nan put_len_field:
5146122d57eSWang Nan bt_ctf_field_put(len_field);
5156122d57eSWang Nan put_len_type:
5166122d57eSWang Nan bt_ctf_field_type_put(len_type);
5176122d57eSWang Nan return ret;
5186122d57eSWang Nan }
5196122d57eSWang Nan
520a3073c8eSGeneviève Bastien static int
add_callchain_output_values(struct bt_ctf_event_class * event_class,struct bt_ctf_event * event,struct ip_callchain * callchain)521a3073c8eSGeneviève Bastien add_callchain_output_values(struct bt_ctf_event_class *event_class,
522a3073c8eSGeneviève Bastien struct bt_ctf_event *event,
523a3073c8eSGeneviève Bastien struct ip_callchain *callchain)
524a3073c8eSGeneviève Bastien {
525a3073c8eSGeneviève Bastien struct bt_ctf_field_type *len_type, *seq_type;
526a3073c8eSGeneviève Bastien struct bt_ctf_field *len_field, *seq_field;
527a3073c8eSGeneviève Bastien unsigned int nr_elements = callchain->nr;
528a3073c8eSGeneviève Bastien unsigned int i;
529a3073c8eSGeneviève Bastien int ret;
530a3073c8eSGeneviève Bastien
531a3073c8eSGeneviève Bastien len_type = bt_ctf_event_class_get_field_by_name(
532a3073c8eSGeneviève Bastien event_class, "perf_callchain_size");
533a3073c8eSGeneviève Bastien len_field = bt_ctf_field_create(len_type);
534a3073c8eSGeneviève Bastien if (!len_field) {
535a3073c8eSGeneviève Bastien pr_err("failed to create 'perf_callchain_size' for callchain output event\n");
536a3073c8eSGeneviève Bastien ret = -1;
537a3073c8eSGeneviève Bastien goto put_len_type;
538a3073c8eSGeneviève Bastien }
539a3073c8eSGeneviève Bastien
540a3073c8eSGeneviève Bastien ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements);
541a3073c8eSGeneviève Bastien if (ret) {
542a3073c8eSGeneviève Bastien pr_err("failed to set field value for perf_callchain_size\n");
543a3073c8eSGeneviève Bastien goto put_len_field;
544a3073c8eSGeneviève Bastien }
545a3073c8eSGeneviève Bastien ret = bt_ctf_event_set_payload(event, "perf_callchain_size", len_field);
546a3073c8eSGeneviève Bastien if (ret) {
547a3073c8eSGeneviève Bastien pr_err("failed to set payload to perf_callchain_size\n");
548a3073c8eSGeneviève Bastien goto put_len_field;
549a3073c8eSGeneviève Bastien }
550a3073c8eSGeneviève Bastien
551a3073c8eSGeneviève Bastien seq_type = bt_ctf_event_class_get_field_by_name(
552a3073c8eSGeneviève Bastien event_class, "perf_callchain");
553a3073c8eSGeneviève Bastien seq_field = bt_ctf_field_create(seq_type);
554a3073c8eSGeneviève Bastien if (!seq_field) {
555a3073c8eSGeneviève Bastien pr_err("failed to create 'perf_callchain' for callchain output event\n");
556a3073c8eSGeneviève Bastien ret = -1;
557a3073c8eSGeneviève Bastien goto put_seq_type;
558a3073c8eSGeneviève Bastien }
559a3073c8eSGeneviève Bastien
560a3073c8eSGeneviève Bastien ret = bt_ctf_field_sequence_set_length(seq_field, len_field);
561a3073c8eSGeneviève Bastien if (ret) {
562a3073c8eSGeneviève Bastien pr_err("failed to set length of 'perf_callchain'\n");
563a3073c8eSGeneviève Bastien goto put_seq_field;
564a3073c8eSGeneviève Bastien }
565a3073c8eSGeneviève Bastien
566a3073c8eSGeneviève Bastien for (i = 0; i < nr_elements; i++) {
567a3073c8eSGeneviève Bastien struct bt_ctf_field *elem_field =
568a3073c8eSGeneviève Bastien bt_ctf_field_sequence_get_field(seq_field, i);
569a3073c8eSGeneviève Bastien
570a3073c8eSGeneviève Bastien ret = bt_ctf_field_unsigned_integer_set_value(elem_field,
571a3073c8eSGeneviève Bastien ((u64 *)(callchain->ips))[i]);
572a3073c8eSGeneviève Bastien
573a3073c8eSGeneviève Bastien bt_ctf_field_put(elem_field);
574a3073c8eSGeneviève Bastien if (ret) {
575a3073c8eSGeneviève Bastien pr_err("failed to set callchain[%d]\n", i);
576a3073c8eSGeneviève Bastien goto put_seq_field;
577a3073c8eSGeneviève Bastien }
578a3073c8eSGeneviève Bastien }
579a3073c8eSGeneviève Bastien
580a3073c8eSGeneviève Bastien ret = bt_ctf_event_set_payload(event, "perf_callchain", seq_field);
581a3073c8eSGeneviève Bastien if (ret)
582a3073c8eSGeneviève Bastien pr_err("failed to set payload for raw_data\n");
583a3073c8eSGeneviève Bastien
584a3073c8eSGeneviève Bastien put_seq_field:
585a3073c8eSGeneviève Bastien bt_ctf_field_put(seq_field);
586a3073c8eSGeneviève Bastien put_seq_type:
587a3073c8eSGeneviève Bastien bt_ctf_field_type_put(seq_type);
588a3073c8eSGeneviève Bastien put_len_field:
589a3073c8eSGeneviève Bastien bt_ctf_field_put(len_field);
590a3073c8eSGeneviève Bastien put_len_type:
591a3073c8eSGeneviève Bastien bt_ctf_field_type_put(len_type);
592a3073c8eSGeneviève Bastien return ret;
593a3073c8eSGeneviève Bastien }
594a3073c8eSGeneviève Bastien
add_generic_values(struct ctf_writer * cw,struct bt_ctf_event * event,struct evsel * evsel,struct perf_sample * sample)595edbe9817SJiri Olsa static int add_generic_values(struct ctf_writer *cw,
596edbe9817SJiri Olsa struct bt_ctf_event *event,
59732dcd021SJiri Olsa struct evsel *evsel,
598edbe9817SJiri Olsa struct perf_sample *sample)
599edbe9817SJiri Olsa {
6001fc632ceSJiri Olsa u64 type = evsel->core.attr.sample_type;
601edbe9817SJiri Olsa int ret;
602edbe9817SJiri Olsa
603edbe9817SJiri Olsa /*
604edbe9817SJiri Olsa * missing:
605edbe9817SJiri Olsa * PERF_SAMPLE_TIME - not needed as we have it in
606edbe9817SJiri Olsa * ctf event header
607edbe9817SJiri Olsa * PERF_SAMPLE_READ - TODO
608edbe9817SJiri Olsa * PERF_SAMPLE_RAW - tracepoint fields are handled separately
609edbe9817SJiri Olsa * PERF_SAMPLE_BRANCH_STACK - TODO
610edbe9817SJiri Olsa * PERF_SAMPLE_REGS_USER - TODO
611edbe9817SJiri Olsa * PERF_SAMPLE_STACK_USER - TODO
612edbe9817SJiri Olsa */
613edbe9817SJiri Olsa
614edbe9817SJiri Olsa if (type & PERF_SAMPLE_IP) {
61554cf776aSSebastian Andrzej Siewior ret = value_set_u64_hex(cw, event, "perf_ip", sample->ip);
616edbe9817SJiri Olsa if (ret)
617edbe9817SJiri Olsa return -1;
618edbe9817SJiri Olsa }
619edbe9817SJiri Olsa
620edbe9817SJiri Olsa if (type & PERF_SAMPLE_TID) {
62154cf776aSSebastian Andrzej Siewior ret = value_set_s32(cw, event, "perf_tid", sample->tid);
622edbe9817SJiri Olsa if (ret)
623edbe9817SJiri Olsa return -1;
624edbe9817SJiri Olsa
62554cf776aSSebastian Andrzej Siewior ret = value_set_s32(cw, event, "perf_pid", sample->pid);
626edbe9817SJiri Olsa if (ret)
627edbe9817SJiri Olsa return -1;
628edbe9817SJiri Olsa }
629edbe9817SJiri Olsa
630edbe9817SJiri Olsa if ((type & PERF_SAMPLE_ID) ||
631edbe9817SJiri Olsa (type & PERF_SAMPLE_IDENTIFIER)) {
63254cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_id", sample->id);
633edbe9817SJiri Olsa if (ret)
634edbe9817SJiri Olsa return -1;
635edbe9817SJiri Olsa }
636edbe9817SJiri Olsa
637edbe9817SJiri Olsa if (type & PERF_SAMPLE_STREAM_ID) {
63854cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_stream_id", sample->stream_id);
639edbe9817SJiri Olsa if (ret)
640edbe9817SJiri Olsa return -1;
641edbe9817SJiri Olsa }
642edbe9817SJiri Olsa
643edbe9817SJiri Olsa if (type & PERF_SAMPLE_PERIOD) {
64454cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_period", sample->period);
645edbe9817SJiri Olsa if (ret)
646edbe9817SJiri Olsa return -1;
647edbe9817SJiri Olsa }
648edbe9817SJiri Olsa
649edbe9817SJiri Olsa if (type & PERF_SAMPLE_WEIGHT) {
65054cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_weight", sample->weight);
651edbe9817SJiri Olsa if (ret)
652edbe9817SJiri Olsa return -1;
653edbe9817SJiri Olsa }
654edbe9817SJiri Olsa
655edbe9817SJiri Olsa if (type & PERF_SAMPLE_DATA_SRC) {
65654cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_data_src",
65754cf776aSSebastian Andrzej Siewior sample->data_src);
658edbe9817SJiri Olsa if (ret)
659edbe9817SJiri Olsa return -1;
660edbe9817SJiri Olsa }
661edbe9817SJiri Olsa
662edbe9817SJiri Olsa if (type & PERF_SAMPLE_TRANSACTION) {
66354cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_transaction",
66454cf776aSSebastian Andrzej Siewior sample->transaction);
665edbe9817SJiri Olsa if (ret)
666edbe9817SJiri Olsa return -1;
667edbe9817SJiri Olsa }
668edbe9817SJiri Olsa
669edbe9817SJiri Olsa return 0;
670edbe9817SJiri Olsa }
671edbe9817SJiri Olsa
ctf_stream__flush(struct ctf_stream * cs)67290e129ffSSebastian Andrzej Siewior static int ctf_stream__flush(struct ctf_stream *cs)
67390e129ffSSebastian Andrzej Siewior {
67490e129ffSSebastian Andrzej Siewior int err = 0;
67590e129ffSSebastian Andrzej Siewior
67690e129ffSSebastian Andrzej Siewior if (cs) {
67790e129ffSSebastian Andrzej Siewior err = bt_ctf_stream_flush(cs->stream);
67890e129ffSSebastian Andrzej Siewior if (err)
67990e129ffSSebastian Andrzej Siewior pr_err("CTF stream %d flush failed\n", cs->cpu);
68090e129ffSSebastian Andrzej Siewior
68189e5fa88SJiri Olsa pr("Flush stream for cpu %d (%u samples)\n",
68289e5fa88SJiri Olsa cs->cpu, cs->count);
68389e5fa88SJiri Olsa
68489e5fa88SJiri Olsa cs->count = 0;
68590e129ffSSebastian Andrzej Siewior }
68690e129ffSSebastian Andrzej Siewior
68790e129ffSSebastian Andrzej Siewior return err;
68890e129ffSSebastian Andrzej Siewior }
68990e129ffSSebastian Andrzej Siewior
ctf_stream__create(struct ctf_writer * cw,int cpu)69090e129ffSSebastian Andrzej Siewior static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu)
69190e129ffSSebastian Andrzej Siewior {
69290e129ffSSebastian Andrzej Siewior struct ctf_stream *cs;
69390e129ffSSebastian Andrzej Siewior struct bt_ctf_field *pkt_ctx = NULL;
69490e129ffSSebastian Andrzej Siewior struct bt_ctf_field *cpu_field = NULL;
69590e129ffSSebastian Andrzej Siewior struct bt_ctf_stream *stream = NULL;
69690e129ffSSebastian Andrzej Siewior int ret;
69790e129ffSSebastian Andrzej Siewior
69890e129ffSSebastian Andrzej Siewior cs = zalloc(sizeof(*cs));
69990e129ffSSebastian Andrzej Siewior if (!cs) {
70090e129ffSSebastian Andrzej Siewior pr_err("Failed to allocate ctf stream\n");
70190e129ffSSebastian Andrzej Siewior return NULL;
70290e129ffSSebastian Andrzej Siewior }
70390e129ffSSebastian Andrzej Siewior
70490e129ffSSebastian Andrzej Siewior stream = bt_ctf_writer_create_stream(cw->writer, cw->stream_class);
70590e129ffSSebastian Andrzej Siewior if (!stream) {
70690e129ffSSebastian Andrzej Siewior pr_err("Failed to create CTF stream\n");
70790e129ffSSebastian Andrzej Siewior goto out;
70890e129ffSSebastian Andrzej Siewior }
70990e129ffSSebastian Andrzej Siewior
71090e129ffSSebastian Andrzej Siewior pkt_ctx = bt_ctf_stream_get_packet_context(stream);
71190e129ffSSebastian Andrzej Siewior if (!pkt_ctx) {
71290e129ffSSebastian Andrzej Siewior pr_err("Failed to obtain packet context\n");
71390e129ffSSebastian Andrzej Siewior goto out;
71490e129ffSSebastian Andrzej Siewior }
71590e129ffSSebastian Andrzej Siewior
71690e129ffSSebastian Andrzej Siewior cpu_field = bt_ctf_field_structure_get_field(pkt_ctx, "cpu_id");
71790e129ffSSebastian Andrzej Siewior bt_ctf_field_put(pkt_ctx);
71890e129ffSSebastian Andrzej Siewior if (!cpu_field) {
71990e129ffSSebastian Andrzej Siewior pr_err("Failed to obtain cpu field\n");
72090e129ffSSebastian Andrzej Siewior goto out;
72190e129ffSSebastian Andrzej Siewior }
72290e129ffSSebastian Andrzej Siewior
72390e129ffSSebastian Andrzej Siewior ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu);
72490e129ffSSebastian Andrzej Siewior if (ret) {
72590e129ffSSebastian Andrzej Siewior pr_err("Failed to update CPU number\n");
72690e129ffSSebastian Andrzej Siewior goto out;
72790e129ffSSebastian Andrzej Siewior }
72890e129ffSSebastian Andrzej Siewior
72990e129ffSSebastian Andrzej Siewior bt_ctf_field_put(cpu_field);
73090e129ffSSebastian Andrzej Siewior
73190e129ffSSebastian Andrzej Siewior cs->cpu = cpu;
73290e129ffSSebastian Andrzej Siewior cs->stream = stream;
73390e129ffSSebastian Andrzej Siewior return cs;
73490e129ffSSebastian Andrzej Siewior
73590e129ffSSebastian Andrzej Siewior out:
73690e129ffSSebastian Andrzej Siewior if (cpu_field)
73790e129ffSSebastian Andrzej Siewior bt_ctf_field_put(cpu_field);
73890e129ffSSebastian Andrzej Siewior if (stream)
73990e129ffSSebastian Andrzej Siewior bt_ctf_stream_put(stream);
74090e129ffSSebastian Andrzej Siewior
74190e129ffSSebastian Andrzej Siewior free(cs);
74290e129ffSSebastian Andrzej Siewior return NULL;
74390e129ffSSebastian Andrzej Siewior }
74490e129ffSSebastian Andrzej Siewior
ctf_stream__delete(struct ctf_stream * cs)74590e129ffSSebastian Andrzej Siewior static void ctf_stream__delete(struct ctf_stream *cs)
74690e129ffSSebastian Andrzej Siewior {
74790e129ffSSebastian Andrzej Siewior if (cs) {
74890e129ffSSebastian Andrzej Siewior bt_ctf_stream_put(cs->stream);
74990e129ffSSebastian Andrzej Siewior free(cs);
75090e129ffSSebastian Andrzej Siewior }
75190e129ffSSebastian Andrzej Siewior }
75290e129ffSSebastian Andrzej Siewior
ctf_stream(struct ctf_writer * cw,int cpu)75390e129ffSSebastian Andrzej Siewior static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu)
75490e129ffSSebastian Andrzej Siewior {
75590e129ffSSebastian Andrzej Siewior struct ctf_stream *cs = cw->stream[cpu];
75690e129ffSSebastian Andrzej Siewior
75790e129ffSSebastian Andrzej Siewior if (!cs) {
75890e129ffSSebastian Andrzej Siewior cs = ctf_stream__create(cw, cpu);
75990e129ffSSebastian Andrzej Siewior cw->stream[cpu] = cs;
76090e129ffSSebastian Andrzej Siewior }
76190e129ffSSebastian Andrzej Siewior
76290e129ffSSebastian Andrzej Siewior return cs;
76390e129ffSSebastian Andrzej Siewior }
76490e129ffSSebastian Andrzej Siewior
get_sample_cpu(struct ctf_writer * cw,struct perf_sample * sample,struct evsel * evsel)76590e129ffSSebastian Andrzej Siewior static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample,
76632dcd021SJiri Olsa struct evsel *evsel)
76790e129ffSSebastian Andrzej Siewior {
76890e129ffSSebastian Andrzej Siewior int cpu = 0;
76990e129ffSSebastian Andrzej Siewior
7701fc632ceSJiri Olsa if (evsel->core.attr.sample_type & PERF_SAMPLE_CPU)
77190e129ffSSebastian Andrzej Siewior cpu = sample->cpu;
77290e129ffSSebastian Andrzej Siewior
77390e129ffSSebastian Andrzej Siewior if (cpu > cw->stream_cnt) {
77490e129ffSSebastian Andrzej Siewior pr_err("Event was recorded for CPU %d, limit is at %d.\n",
77590e129ffSSebastian Andrzej Siewior cpu, cw->stream_cnt);
77690e129ffSSebastian Andrzej Siewior cpu = 0;
77790e129ffSSebastian Andrzej Siewior }
77890e129ffSSebastian Andrzej Siewior
77990e129ffSSebastian Andrzej Siewior return cpu;
78090e129ffSSebastian Andrzej Siewior }
78190e129ffSSebastian Andrzej Siewior
78289e5fa88SJiri Olsa #define STREAM_FLUSH_COUNT 100000
78389e5fa88SJiri Olsa
78489e5fa88SJiri Olsa /*
78589e5fa88SJiri Olsa * Currently we have no other way to determine the
78689e5fa88SJiri Olsa * time for the stream flush other than keep track
78789e5fa88SJiri Olsa * of the number of events and check it against
78889e5fa88SJiri Olsa * threshold.
78989e5fa88SJiri Olsa */
is_flush_needed(struct ctf_stream * cs)79089e5fa88SJiri Olsa static bool is_flush_needed(struct ctf_stream *cs)
79189e5fa88SJiri Olsa {
79289e5fa88SJiri Olsa return cs->count >= STREAM_FLUSH_COUNT;
79389e5fa88SJiri Olsa }
79489e5fa88SJiri Olsa
process_sample_event(struct perf_tool * tool,union perf_event * _event,struct perf_sample * sample,struct evsel * evsel,struct machine * machine __maybe_unused)795edbe9817SJiri Olsa static int process_sample_event(struct perf_tool *tool,
796b8f8eb84SArnaldo Carvalho de Melo union perf_event *_event,
797edbe9817SJiri Olsa struct perf_sample *sample,
79832dcd021SJiri Olsa struct evsel *evsel,
799edbe9817SJiri Olsa struct machine *machine __maybe_unused)
800edbe9817SJiri Olsa {
801edbe9817SJiri Olsa struct convert *c = container_of(tool, struct convert, tool);
802edbe9817SJiri Olsa struct evsel_priv *priv = evsel->priv;
803edbe9817SJiri Olsa struct ctf_writer *cw = &c->writer;
80490e129ffSSebastian Andrzej Siewior struct ctf_stream *cs;
805edbe9817SJiri Olsa struct bt_ctf_event_class *event_class;
806edbe9817SJiri Olsa struct bt_ctf_event *event;
807edbe9817SJiri Olsa int ret;
8081fc632ceSJiri Olsa unsigned long type = evsel->core.attr.sample_type;
809edbe9817SJiri Olsa
810edbe9817SJiri Olsa if (WARN_ONCE(!priv, "Failed to setup all events.\n"))
811edbe9817SJiri Olsa return 0;
812edbe9817SJiri Olsa
813edbe9817SJiri Olsa event_class = priv->event_class;
814edbe9817SJiri Olsa
815edbe9817SJiri Olsa /* update stats */
816edbe9817SJiri Olsa c->events_count++;
817edbe9817SJiri Olsa c->events_size += _event->header.size;
818edbe9817SJiri Olsa
819edbe9817SJiri Olsa pr_time2(sample->time, "sample %" PRIu64 "\n", c->events_count);
820edbe9817SJiri Olsa
821edbe9817SJiri Olsa event = bt_ctf_event_create(event_class);
822edbe9817SJiri Olsa if (!event) {
823edbe9817SJiri Olsa pr_err("Failed to create an CTF event\n");
824edbe9817SJiri Olsa return -1;
825edbe9817SJiri Olsa }
826edbe9817SJiri Olsa
827edbe9817SJiri Olsa bt_ctf_clock_set_time(cw->clock, sample->time);
828edbe9817SJiri Olsa
829edbe9817SJiri Olsa ret = add_generic_values(cw, event, evsel, sample);
830edbe9817SJiri Olsa if (ret)
831edbe9817SJiri Olsa return -1;
832edbe9817SJiri Olsa
8331fc632ceSJiri Olsa if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) {
83469364727SSebastian Andrzej Siewior ret = add_tracepoint_values(cw, event_class, event,
83569364727SSebastian Andrzej Siewior evsel, sample);
83669364727SSebastian Andrzej Siewior if (ret)
83769364727SSebastian Andrzej Siewior return -1;
83869364727SSebastian Andrzej Siewior }
83969364727SSebastian Andrzej Siewior
840a3073c8eSGeneviève Bastien if (type & PERF_SAMPLE_CALLCHAIN) {
841a3073c8eSGeneviève Bastien ret = add_callchain_output_values(event_class,
842a3073c8eSGeneviève Bastien event, sample->callchain);
843a3073c8eSGeneviève Bastien if (ret)
844a3073c8eSGeneviève Bastien return -1;
845a3073c8eSGeneviève Bastien }
846a3073c8eSGeneviève Bastien
847c754c382SArnaldo Carvalho de Melo if (evsel__is_bpf_output(evsel)) {
8486122d57eSWang Nan ret = add_bpf_output_values(event_class, event, sample);
8496122d57eSWang Nan if (ret)
8506122d57eSWang Nan return -1;
8516122d57eSWang Nan }
8526122d57eSWang Nan
85390e129ffSSebastian Andrzej Siewior cs = ctf_stream(cw, get_sample_cpu(cw, sample, evsel));
85489e5fa88SJiri Olsa if (cs) {
85589e5fa88SJiri Olsa if (is_flush_needed(cs))
85689e5fa88SJiri Olsa ctf_stream__flush(cs);
85789e5fa88SJiri Olsa
85889e5fa88SJiri Olsa cs->count++;
85990e129ffSSebastian Andrzej Siewior bt_ctf_stream_append_event(cs->stream, event);
86089e5fa88SJiri Olsa }
86190e129ffSSebastian Andrzej Siewior
862edbe9817SJiri Olsa bt_ctf_event_put(event);
86390e129ffSSebastian Andrzej Siewior return cs ? 0 : -1;
864edbe9817SJiri Olsa }
865edbe9817SJiri Olsa
866f5a08cedSWang Nan #define __NON_SAMPLE_SET_FIELD(_name, _type, _field) \
867f5a08cedSWang Nan do { \
868f5a08cedSWang Nan ret = value_set_##_type(cw, event, #_field, _event->_name._field);\
869f5a08cedSWang Nan if (ret) \
870f5a08cedSWang Nan return -1; \
871f5a08cedSWang Nan } while(0)
872f5a08cedSWang Nan
873f5a08cedSWang Nan #define __FUNC_PROCESS_NON_SAMPLE(_name, body) \
874f5a08cedSWang Nan static int process_##_name##_event(struct perf_tool *tool, \
875f5a08cedSWang Nan union perf_event *_event, \
876f5a08cedSWang Nan struct perf_sample *sample, \
877f5a08cedSWang Nan struct machine *machine) \
878f5a08cedSWang Nan { \
879f5a08cedSWang Nan struct convert *c = container_of(tool, struct convert, tool);\
880f5a08cedSWang Nan struct ctf_writer *cw = &c->writer; \
881f5a08cedSWang Nan struct bt_ctf_event_class *event_class = cw->_name##_class;\
882f5a08cedSWang Nan struct bt_ctf_event *event; \
883f5a08cedSWang Nan struct ctf_stream *cs; \
884f5a08cedSWang Nan int ret; \
885f5a08cedSWang Nan \
886f5a08cedSWang Nan c->non_sample_count++; \
887f5a08cedSWang Nan c->events_size += _event->header.size; \
888f5a08cedSWang Nan event = bt_ctf_event_create(event_class); \
889f5a08cedSWang Nan if (!event) { \
890f5a08cedSWang Nan pr_err("Failed to create an CTF event\n"); \
891f5a08cedSWang Nan return -1; \
892f5a08cedSWang Nan } \
893f5a08cedSWang Nan \
894f5a08cedSWang Nan bt_ctf_clock_set_time(cw->clock, sample->time); \
895f5a08cedSWang Nan body \
896f5a08cedSWang Nan cs = ctf_stream(cw, 0); \
897f5a08cedSWang Nan if (cs) { \
898f5a08cedSWang Nan if (is_flush_needed(cs)) \
899f5a08cedSWang Nan ctf_stream__flush(cs); \
900f5a08cedSWang Nan \
901f5a08cedSWang Nan cs->count++; \
902f5a08cedSWang Nan bt_ctf_stream_append_event(cs->stream, event); \
903f5a08cedSWang Nan } \
904f5a08cedSWang Nan bt_ctf_event_put(event); \
905f5a08cedSWang Nan \
906f5a08cedSWang Nan return perf_event__process_##_name(tool, _event, sample, machine);\
907f5a08cedSWang Nan }
908f5a08cedSWang Nan
__FUNC_PROCESS_NON_SAMPLE(comm,__NON_SAMPLE_SET_FIELD (comm,u32,pid);__NON_SAMPLE_SET_FIELD (comm,u32,tid);__NON_SAMPLE_SET_FIELD (comm,string,comm);)909f5a08cedSWang Nan __FUNC_PROCESS_NON_SAMPLE(comm,
910f5a08cedSWang Nan __NON_SAMPLE_SET_FIELD(comm, u32, pid);
911f5a08cedSWang Nan __NON_SAMPLE_SET_FIELD(comm, u32, tid);
912f5a08cedSWang Nan __NON_SAMPLE_SET_FIELD(comm, string, comm);
913f5a08cedSWang Nan )
914ebccba3fSWang Nan __FUNC_PROCESS_NON_SAMPLE(fork,
915ebccba3fSWang Nan __NON_SAMPLE_SET_FIELD(fork, u32, pid);
916ebccba3fSWang Nan __NON_SAMPLE_SET_FIELD(fork, u32, ppid);
917ebccba3fSWang Nan __NON_SAMPLE_SET_FIELD(fork, u32, tid);
918ebccba3fSWang Nan __NON_SAMPLE_SET_FIELD(fork, u32, ptid);
919ebccba3fSWang Nan __NON_SAMPLE_SET_FIELD(fork, u64, time);
920ebccba3fSWang Nan )
921ebccba3fSWang Nan
922ebccba3fSWang Nan __FUNC_PROCESS_NON_SAMPLE(exit,
923ebccba3fSWang Nan __NON_SAMPLE_SET_FIELD(fork, u32, pid);
924ebccba3fSWang Nan __NON_SAMPLE_SET_FIELD(fork, u32, ppid);
925ebccba3fSWang Nan __NON_SAMPLE_SET_FIELD(fork, u32, tid);
926ebccba3fSWang Nan __NON_SAMPLE_SET_FIELD(fork, u32, ptid);
927ebccba3fSWang Nan __NON_SAMPLE_SET_FIELD(fork, u64, time);
928ebccba3fSWang Nan )
929f9f6f2a9SGeneviève Bastien __FUNC_PROCESS_NON_SAMPLE(mmap,
930f9f6f2a9SGeneviève Bastien __NON_SAMPLE_SET_FIELD(mmap, u32, pid);
931f9f6f2a9SGeneviève Bastien __NON_SAMPLE_SET_FIELD(mmap, u32, tid);
932f9f6f2a9SGeneviève Bastien __NON_SAMPLE_SET_FIELD(mmap, u64_hex, start);
933f9f6f2a9SGeneviève Bastien __NON_SAMPLE_SET_FIELD(mmap, string, filename);
934f9f6f2a9SGeneviève Bastien )
935f9f6f2a9SGeneviève Bastien __FUNC_PROCESS_NON_SAMPLE(mmap2,
936f9f6f2a9SGeneviève Bastien __NON_SAMPLE_SET_FIELD(mmap2, u32, pid);
937f9f6f2a9SGeneviève Bastien __NON_SAMPLE_SET_FIELD(mmap2, u32, tid);
938f9f6f2a9SGeneviève Bastien __NON_SAMPLE_SET_FIELD(mmap2, u64_hex, start);
939f9f6f2a9SGeneviève Bastien __NON_SAMPLE_SET_FIELD(mmap2, string, filename);
940f9f6f2a9SGeneviève Bastien )
941f5a08cedSWang Nan #undef __NON_SAMPLE_SET_FIELD
942f5a08cedSWang Nan #undef __FUNC_PROCESS_NON_SAMPLE
943f5a08cedSWang Nan
944e0a7cce5SWang Nan /* If dup < 0, add a prefix. Else, add _dupl_X suffix. */
945e0a7cce5SWang Nan static char *change_name(char *name, char *orig_name, int dup)
946e0a7cce5SWang Nan {
947e0a7cce5SWang Nan char *new_name = NULL;
948e0a7cce5SWang Nan size_t len;
949e0a7cce5SWang Nan
950e0a7cce5SWang Nan if (!name)
951e0a7cce5SWang Nan name = orig_name;
952e0a7cce5SWang Nan
953e0a7cce5SWang Nan if (dup >= 10)
954e0a7cce5SWang Nan goto out;
955e0a7cce5SWang Nan /*
956e0a7cce5SWang Nan * Add '_' prefix to potential keywork. According to
9576edfd0ebSKees Cook * Mathieu Desnoyers (https://lore.kernel.org/lkml/1074266107.40857.1422045946295.JavaMail.zimbra@efficios.com),
9584d39c89fSIngo Molnar * further CTF spec updating may require us to use '$'.
959e0a7cce5SWang Nan */
960e0a7cce5SWang Nan if (dup < 0)
961e0a7cce5SWang Nan len = strlen(name) + sizeof("_");
962e0a7cce5SWang Nan else
963e0a7cce5SWang Nan len = strlen(orig_name) + sizeof("_dupl_X");
964e0a7cce5SWang Nan
965e0a7cce5SWang Nan new_name = malloc(len);
966e0a7cce5SWang Nan if (!new_name)
967e0a7cce5SWang Nan goto out;
968e0a7cce5SWang Nan
969e0a7cce5SWang Nan if (dup < 0)
970e0a7cce5SWang Nan snprintf(new_name, len, "_%s", name);
971e0a7cce5SWang Nan else
972e0a7cce5SWang Nan snprintf(new_name, len, "%s_dupl_%d", orig_name, dup);
973e0a7cce5SWang Nan
974e0a7cce5SWang Nan out:
975e0a7cce5SWang Nan if (name != orig_name)
976e0a7cce5SWang Nan free(name);
977e0a7cce5SWang Nan return new_name;
978e0a7cce5SWang Nan }
979e0a7cce5SWang Nan
event_class_add_field(struct bt_ctf_event_class * event_class,struct bt_ctf_field_type * type,struct tep_format_field * field)980e0a7cce5SWang Nan static int event_class_add_field(struct bt_ctf_event_class *event_class,
981e0a7cce5SWang Nan struct bt_ctf_field_type *type,
9822c92f982STzvetomir Stoyanov (VMware) struct tep_format_field *field)
983e0a7cce5SWang Nan {
984e0a7cce5SWang Nan struct bt_ctf_field_type *t = NULL;
985e0a7cce5SWang Nan char *name;
986e0a7cce5SWang Nan int dup = 1;
987e0a7cce5SWang Nan int ret;
988e0a7cce5SWang Nan
989e0a7cce5SWang Nan /* alias was already assigned */
990e0a7cce5SWang Nan if (field->alias != field->name)
991e0a7cce5SWang Nan return bt_ctf_event_class_add_field(event_class, type,
992e0a7cce5SWang Nan (char *)field->alias);
993e0a7cce5SWang Nan
994e0a7cce5SWang Nan name = field->name;
995e0a7cce5SWang Nan
996e0a7cce5SWang Nan /* If 'name' is a keywork, add prefix. */
997e0a7cce5SWang Nan if (bt_ctf_validate_identifier(name))
998e0a7cce5SWang Nan name = change_name(name, field->name, -1);
999e0a7cce5SWang Nan
1000e0a7cce5SWang Nan if (!name) {
1001e0a7cce5SWang Nan pr_err("Failed to fix invalid identifier.");
1002e0a7cce5SWang Nan return -1;
1003e0a7cce5SWang Nan }
1004e0a7cce5SWang Nan while ((t = bt_ctf_event_class_get_field_by_name(event_class, name))) {
1005e0a7cce5SWang Nan bt_ctf_field_type_put(t);
1006e0a7cce5SWang Nan name = change_name(name, field->name, dup++);
1007e0a7cce5SWang Nan if (!name) {
1008e0a7cce5SWang Nan pr_err("Failed to create dup name for '%s'\n", field->name);
1009e0a7cce5SWang Nan return -1;
1010e0a7cce5SWang Nan }
1011e0a7cce5SWang Nan }
1012e0a7cce5SWang Nan
1013e0a7cce5SWang Nan ret = bt_ctf_event_class_add_field(event_class, type, name);
1014e0a7cce5SWang Nan if (!ret)
1015e0a7cce5SWang Nan field->alias = name;
1016e0a7cce5SWang Nan
1017e0a7cce5SWang Nan return ret;
1018e0a7cce5SWang Nan }
1019e0a7cce5SWang Nan
add_tracepoint_fields_types(struct ctf_writer * cw,struct tep_format_field * fields,struct bt_ctf_event_class * event_class)102069364727SSebastian Andrzej Siewior static int add_tracepoint_fields_types(struct ctf_writer *cw,
10212c92f982STzvetomir Stoyanov (VMware) struct tep_format_field *fields,
102269364727SSebastian Andrzej Siewior struct bt_ctf_event_class *event_class)
102369364727SSebastian Andrzej Siewior {
10242c92f982STzvetomir Stoyanov (VMware) struct tep_format_field *field;
102569364727SSebastian Andrzej Siewior int ret;
102669364727SSebastian Andrzej Siewior
102769364727SSebastian Andrzej Siewior for (field = fields; field; field = field->next) {
102869364727SSebastian Andrzej Siewior struct bt_ctf_field_type *type;
102969364727SSebastian Andrzej Siewior unsigned long flags = field->flags;
103069364727SSebastian Andrzej Siewior
103169364727SSebastian Andrzej Siewior pr2(" field '%s'\n", field->name);
103269364727SSebastian Andrzej Siewior
103369364727SSebastian Andrzej Siewior type = get_tracepoint_field_type(cw, field);
103469364727SSebastian Andrzej Siewior if (!type)
103569364727SSebastian Andrzej Siewior return -1;
103669364727SSebastian Andrzej Siewior
103769364727SSebastian Andrzej Siewior /*
103869364727SSebastian Andrzej Siewior * A string is an array of chars. For this we use the string
103969364727SSebastian Andrzej Siewior * type and don't care that it is an array. What we don't
104069364727SSebastian Andrzej Siewior * support is an array of strings.
104169364727SSebastian Andrzej Siewior */
1042bb39ccb2STzvetomir Stoyanov (VMware) if (flags & TEP_FIELD_IS_STRING)
1043bb39ccb2STzvetomir Stoyanov (VMware) flags &= ~TEP_FIELD_IS_ARRAY;
104469364727SSebastian Andrzej Siewior
1045bb39ccb2STzvetomir Stoyanov (VMware) if (flags & TEP_FIELD_IS_ARRAY)
104669364727SSebastian Andrzej Siewior type = bt_ctf_field_type_array_create(type, field->arraylen);
104769364727SSebastian Andrzej Siewior
1048e0a7cce5SWang Nan ret = event_class_add_field(event_class, type, field);
104969364727SSebastian Andrzej Siewior
1050bb39ccb2STzvetomir Stoyanov (VMware) if (flags & TEP_FIELD_IS_ARRAY)
105169364727SSebastian Andrzej Siewior bt_ctf_field_type_put(type);
105269364727SSebastian Andrzej Siewior
105369364727SSebastian Andrzej Siewior if (ret) {
1054e0a7cce5SWang Nan pr_err("Failed to add field '%s': %d\n",
1055e0a7cce5SWang Nan field->name, ret);
105669364727SSebastian Andrzej Siewior return -1;
105769364727SSebastian Andrzej Siewior }
105869364727SSebastian Andrzej Siewior }
105969364727SSebastian Andrzej Siewior
106069364727SSebastian Andrzej Siewior return 0;
106169364727SSebastian Andrzej Siewior }
106269364727SSebastian Andrzej Siewior
add_tracepoint_types(struct ctf_writer * cw,struct evsel * evsel,struct bt_ctf_event_class * class)106369364727SSebastian Andrzej Siewior static int add_tracepoint_types(struct ctf_writer *cw,
106432dcd021SJiri Olsa struct evsel *evsel,
106569364727SSebastian Andrzej Siewior struct bt_ctf_event_class *class)
106669364727SSebastian Andrzej Siewior {
10672c92f982STzvetomir Stoyanov (VMware) struct tep_format_field *common_fields = evsel->tp_format->format.common_fields;
10682c92f982STzvetomir Stoyanov (VMware) struct tep_format_field *fields = evsel->tp_format->format.fields;
106969364727SSebastian Andrzej Siewior int ret;
107069364727SSebastian Andrzej Siewior
107169364727SSebastian Andrzej Siewior ret = add_tracepoint_fields_types(cw, common_fields, class);
107269364727SSebastian Andrzej Siewior if (!ret)
107369364727SSebastian Andrzej Siewior ret = add_tracepoint_fields_types(cw, fields, class);
107469364727SSebastian Andrzej Siewior
107569364727SSebastian Andrzej Siewior return ret;
107669364727SSebastian Andrzej Siewior }
107769364727SSebastian Andrzej Siewior
add_bpf_output_types(struct ctf_writer * cw,struct bt_ctf_event_class * class)10786122d57eSWang Nan static int add_bpf_output_types(struct ctf_writer *cw,
10796122d57eSWang Nan struct bt_ctf_event_class *class)
10806122d57eSWang Nan {
10816122d57eSWang Nan struct bt_ctf_field_type *len_type = cw->data.u32;
10826122d57eSWang Nan struct bt_ctf_field_type *seq_base_type = cw->data.u32_hex;
10836122d57eSWang Nan struct bt_ctf_field_type *seq_type;
10846122d57eSWang Nan int ret;
10856122d57eSWang Nan
10866122d57eSWang Nan ret = bt_ctf_event_class_add_field(class, len_type, "raw_len");
10876122d57eSWang Nan if (ret)
10886122d57eSWang Nan return ret;
10896122d57eSWang Nan
10906122d57eSWang Nan seq_type = bt_ctf_field_type_sequence_create(seq_base_type, "raw_len");
10916122d57eSWang Nan if (!seq_type)
10926122d57eSWang Nan return -1;
10936122d57eSWang Nan
10946122d57eSWang Nan return bt_ctf_event_class_add_field(class, seq_type, "raw_data");
10956122d57eSWang Nan }
10966122d57eSWang Nan
add_generic_types(struct ctf_writer * cw,struct evsel * evsel,struct bt_ctf_event_class * event_class)109732dcd021SJiri Olsa static int add_generic_types(struct ctf_writer *cw, struct evsel *evsel,
1098edbe9817SJiri Olsa struct bt_ctf_event_class *event_class)
1099edbe9817SJiri Olsa {
11001fc632ceSJiri Olsa u64 type = evsel->core.attr.sample_type;
1101edbe9817SJiri Olsa
1102edbe9817SJiri Olsa /*
1103edbe9817SJiri Olsa * missing:
1104edbe9817SJiri Olsa * PERF_SAMPLE_TIME - not needed as we have it in
1105edbe9817SJiri Olsa * ctf event header
1106edbe9817SJiri Olsa * PERF_SAMPLE_READ - TODO
1107edbe9817SJiri Olsa * PERF_SAMPLE_CALLCHAIN - TODO
11086122d57eSWang Nan * PERF_SAMPLE_RAW - tracepoint fields and BPF output
11096122d57eSWang Nan * are handled separately
1110edbe9817SJiri Olsa * PERF_SAMPLE_BRANCH_STACK - TODO
1111edbe9817SJiri Olsa * PERF_SAMPLE_REGS_USER - TODO
1112edbe9817SJiri Olsa * PERF_SAMPLE_STACK_USER - TODO
1113edbe9817SJiri Olsa */
1114edbe9817SJiri Olsa
1115edbe9817SJiri Olsa #define ADD_FIELD(cl, t, n) \
1116edbe9817SJiri Olsa do { \
1117edbe9817SJiri Olsa pr2(" field '%s'\n", n); \
1118edbe9817SJiri Olsa if (bt_ctf_event_class_add_field(cl, t, n)) { \
1119e0a7cce5SWang Nan pr_err("Failed to add field '%s';\n", n); \
1120edbe9817SJiri Olsa return -1; \
1121edbe9817SJiri Olsa } \
1122edbe9817SJiri Olsa } while (0)
1123edbe9817SJiri Olsa
1124edbe9817SJiri Olsa if (type & PERF_SAMPLE_IP)
112554cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64_hex, "perf_ip");
1126edbe9817SJiri Olsa
1127edbe9817SJiri Olsa if (type & PERF_SAMPLE_TID) {
112854cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.s32, "perf_tid");
112954cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.s32, "perf_pid");
1130edbe9817SJiri Olsa }
1131edbe9817SJiri Olsa
1132edbe9817SJiri Olsa if ((type & PERF_SAMPLE_ID) ||
1133edbe9817SJiri Olsa (type & PERF_SAMPLE_IDENTIFIER))
113454cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_id");
1135edbe9817SJiri Olsa
1136edbe9817SJiri Olsa if (type & PERF_SAMPLE_STREAM_ID)
113754cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_stream_id");
1138edbe9817SJiri Olsa
1139edbe9817SJiri Olsa if (type & PERF_SAMPLE_PERIOD)
114054cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_period");
1141edbe9817SJiri Olsa
1142edbe9817SJiri Olsa if (type & PERF_SAMPLE_WEIGHT)
114354cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_weight");
1144edbe9817SJiri Olsa
1145edbe9817SJiri Olsa if (type & PERF_SAMPLE_DATA_SRC)
114654cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_data_src");
1147edbe9817SJiri Olsa
1148edbe9817SJiri Olsa if (type & PERF_SAMPLE_TRANSACTION)
114954cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_transaction");
1150edbe9817SJiri Olsa
1151a3073c8eSGeneviève Bastien if (type & PERF_SAMPLE_CALLCHAIN) {
1152a3073c8eSGeneviève Bastien ADD_FIELD(event_class, cw->data.u32, "perf_callchain_size");
1153a3073c8eSGeneviève Bastien ADD_FIELD(event_class,
1154a3073c8eSGeneviève Bastien bt_ctf_field_type_sequence_create(
1155a3073c8eSGeneviève Bastien cw->data.u64_hex, "perf_callchain_size"),
1156a3073c8eSGeneviève Bastien "perf_callchain");
1157a3073c8eSGeneviève Bastien }
1158a3073c8eSGeneviève Bastien
1159edbe9817SJiri Olsa #undef ADD_FIELD
1160edbe9817SJiri Olsa return 0;
1161edbe9817SJiri Olsa }
1162edbe9817SJiri Olsa
add_event(struct ctf_writer * cw,struct evsel * evsel)116332dcd021SJiri Olsa static int add_event(struct ctf_writer *cw, struct evsel *evsel)
1164edbe9817SJiri Olsa {
1165edbe9817SJiri Olsa struct bt_ctf_event_class *event_class;
1166edbe9817SJiri Olsa struct evsel_priv *priv;
11678ab2e96dSArnaldo Carvalho de Melo const char *name = evsel__name(evsel);
1168edbe9817SJiri Olsa int ret;
1169edbe9817SJiri Olsa
11701fc632ceSJiri Olsa pr("Adding event '%s' (type %d)\n", name, evsel->core.attr.type);
1171edbe9817SJiri Olsa
1172edbe9817SJiri Olsa event_class = bt_ctf_event_class_create(name);
1173edbe9817SJiri Olsa if (!event_class)
1174edbe9817SJiri Olsa return -1;
1175edbe9817SJiri Olsa
1176edbe9817SJiri Olsa ret = add_generic_types(cw, evsel, event_class);
1177edbe9817SJiri Olsa if (ret)
1178edbe9817SJiri Olsa goto err;
1179edbe9817SJiri Olsa
11801fc632ceSJiri Olsa if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) {
118169364727SSebastian Andrzej Siewior ret = add_tracepoint_types(cw, evsel, event_class);
118269364727SSebastian Andrzej Siewior if (ret)
118369364727SSebastian Andrzej Siewior goto err;
118469364727SSebastian Andrzej Siewior }
118569364727SSebastian Andrzej Siewior
1186c754c382SArnaldo Carvalho de Melo if (evsel__is_bpf_output(evsel)) {
11876122d57eSWang Nan ret = add_bpf_output_types(cw, event_class);
11886122d57eSWang Nan if (ret)
11896122d57eSWang Nan goto err;
11906122d57eSWang Nan }
11916122d57eSWang Nan
1192edbe9817SJiri Olsa ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);
1193edbe9817SJiri Olsa if (ret) {
1194edbe9817SJiri Olsa pr("Failed to add event class into stream.\n");
1195edbe9817SJiri Olsa goto err;
1196edbe9817SJiri Olsa }
1197edbe9817SJiri Olsa
1198edbe9817SJiri Olsa priv = malloc(sizeof(*priv));
1199edbe9817SJiri Olsa if (!priv)
1200edbe9817SJiri Olsa goto err;
1201edbe9817SJiri Olsa
1202edbe9817SJiri Olsa priv->event_class = event_class;
1203edbe9817SJiri Olsa evsel->priv = priv;
1204edbe9817SJiri Olsa return 0;
1205edbe9817SJiri Olsa
1206edbe9817SJiri Olsa err:
1207edbe9817SJiri Olsa bt_ctf_event_class_put(event_class);
1208edbe9817SJiri Olsa pr_err("Failed to add event '%s'.\n", name);
1209edbe9817SJiri Olsa return -1;
1210edbe9817SJiri Olsa }
1211edbe9817SJiri Olsa
setup_events(struct ctf_writer * cw,struct perf_session * session)1212edbe9817SJiri Olsa static int setup_events(struct ctf_writer *cw, struct perf_session *session)
1213edbe9817SJiri Olsa {
121463503dbaSJiri Olsa struct evlist *evlist = session->evlist;
121532dcd021SJiri Olsa struct evsel *evsel;
1216edbe9817SJiri Olsa int ret;
1217edbe9817SJiri Olsa
1218e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evlist, evsel) {
1219edbe9817SJiri Olsa ret = add_event(cw, evsel);
1220edbe9817SJiri Olsa if (ret)
1221edbe9817SJiri Olsa return ret;
1222edbe9817SJiri Olsa }
1223edbe9817SJiri Olsa return 0;
1224edbe9817SJiri Olsa }
1225edbe9817SJiri Olsa
1226f5a08cedSWang Nan #define __NON_SAMPLE_ADD_FIELD(t, n) \
1227f5a08cedSWang Nan do { \
1228f5a08cedSWang Nan pr2(" field '%s'\n", #n); \
1229f5a08cedSWang Nan if (bt_ctf_event_class_add_field(event_class, cw->data.t, #n)) {\
1230f5a08cedSWang Nan pr_err("Failed to add field '%s';\n", #n);\
1231f5a08cedSWang Nan return -1; \
1232f5a08cedSWang Nan } \
1233f5a08cedSWang Nan } while(0)
1234f5a08cedSWang Nan
1235f5a08cedSWang Nan #define __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(_name, body) \
1236f5a08cedSWang Nan static int add_##_name##_event(struct ctf_writer *cw) \
1237f5a08cedSWang Nan { \
1238f5a08cedSWang Nan struct bt_ctf_event_class *event_class; \
1239f5a08cedSWang Nan int ret; \
1240f5a08cedSWang Nan \
1241f5a08cedSWang Nan pr("Adding "#_name" event\n"); \
1242f5a08cedSWang Nan event_class = bt_ctf_event_class_create("perf_" #_name);\
1243f5a08cedSWang Nan if (!event_class) \
1244f5a08cedSWang Nan return -1; \
1245f5a08cedSWang Nan body \
1246f5a08cedSWang Nan \
1247f5a08cedSWang Nan ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);\
1248f5a08cedSWang Nan if (ret) { \
1249f5a08cedSWang Nan pr("Failed to add event class '"#_name"' into stream.\n");\
1250f5a08cedSWang Nan return ret; \
1251f5a08cedSWang Nan } \
1252f5a08cedSWang Nan \
1253f5a08cedSWang Nan cw->_name##_class = event_class; \
1254f5a08cedSWang Nan bt_ctf_event_class_put(event_class); \
1255f5a08cedSWang Nan return 0; \
1256f5a08cedSWang Nan }
1257f5a08cedSWang Nan
__FUNC_ADD_NON_SAMPLE_EVENT_CLASS(comm,__NON_SAMPLE_ADD_FIELD (u32,pid);__NON_SAMPLE_ADD_FIELD (u32,tid);__NON_SAMPLE_ADD_FIELD (string,comm);)1258f5a08cedSWang Nan __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(comm,
1259f5a08cedSWang Nan __NON_SAMPLE_ADD_FIELD(u32, pid);
1260f5a08cedSWang Nan __NON_SAMPLE_ADD_FIELD(u32, tid);
1261f5a08cedSWang Nan __NON_SAMPLE_ADD_FIELD(string, comm);
1262f5a08cedSWang Nan )
1263f5a08cedSWang Nan
1264ebccba3fSWang Nan __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(fork,
1265ebccba3fSWang Nan __NON_SAMPLE_ADD_FIELD(u32, pid);
1266ebccba3fSWang Nan __NON_SAMPLE_ADD_FIELD(u32, ppid);
1267ebccba3fSWang Nan __NON_SAMPLE_ADD_FIELD(u32, tid);
1268ebccba3fSWang Nan __NON_SAMPLE_ADD_FIELD(u32, ptid);
1269ebccba3fSWang Nan __NON_SAMPLE_ADD_FIELD(u64, time);
1270ebccba3fSWang Nan )
1271ebccba3fSWang Nan
1272ebccba3fSWang Nan __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(exit,
1273ebccba3fSWang Nan __NON_SAMPLE_ADD_FIELD(u32, pid);
1274ebccba3fSWang Nan __NON_SAMPLE_ADD_FIELD(u32, ppid);
1275ebccba3fSWang Nan __NON_SAMPLE_ADD_FIELD(u32, tid);
1276ebccba3fSWang Nan __NON_SAMPLE_ADD_FIELD(u32, ptid);
1277ebccba3fSWang Nan __NON_SAMPLE_ADD_FIELD(u64, time);
1278ebccba3fSWang Nan )
1279ebccba3fSWang Nan
1280f9f6f2a9SGeneviève Bastien __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(mmap,
1281f9f6f2a9SGeneviève Bastien __NON_SAMPLE_ADD_FIELD(u32, pid);
1282f9f6f2a9SGeneviève Bastien __NON_SAMPLE_ADD_FIELD(u32, tid);
1283f9f6f2a9SGeneviève Bastien __NON_SAMPLE_ADD_FIELD(u64_hex, start);
1284f9f6f2a9SGeneviève Bastien __NON_SAMPLE_ADD_FIELD(string, filename);
1285f9f6f2a9SGeneviève Bastien )
1286f9f6f2a9SGeneviève Bastien
1287f9f6f2a9SGeneviève Bastien __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(mmap2,
1288f9f6f2a9SGeneviève Bastien __NON_SAMPLE_ADD_FIELD(u32, pid);
1289f9f6f2a9SGeneviève Bastien __NON_SAMPLE_ADD_FIELD(u32, tid);
1290f9f6f2a9SGeneviève Bastien __NON_SAMPLE_ADD_FIELD(u64_hex, start);
1291f9f6f2a9SGeneviève Bastien __NON_SAMPLE_ADD_FIELD(string, filename);
1292f9f6f2a9SGeneviève Bastien )
1293f5a08cedSWang Nan #undef __NON_SAMPLE_ADD_FIELD
1294f5a08cedSWang Nan #undef __FUNC_ADD_NON_SAMPLE_EVENT_CLASS
1295f5a08cedSWang Nan
1296f5a08cedSWang Nan static int setup_non_sample_events(struct ctf_writer *cw,
1297f5a08cedSWang Nan struct perf_session *session __maybe_unused)
1298f5a08cedSWang Nan {
1299f5a08cedSWang Nan int ret;
1300f5a08cedSWang Nan
1301f5a08cedSWang Nan ret = add_comm_event(cw);
1302f5a08cedSWang Nan if (ret)
1303f5a08cedSWang Nan return ret;
1304ebccba3fSWang Nan ret = add_exit_event(cw);
1305ebccba3fSWang Nan if (ret)
1306ebccba3fSWang Nan return ret;
1307ebccba3fSWang Nan ret = add_fork_event(cw);
1308ebccba3fSWang Nan if (ret)
1309ebccba3fSWang Nan return ret;
1310f9f6f2a9SGeneviève Bastien ret = add_mmap_event(cw);
1311f9f6f2a9SGeneviève Bastien if (ret)
1312f9f6f2a9SGeneviève Bastien return ret;
1313f9f6f2a9SGeneviève Bastien ret = add_mmap2_event(cw);
1314f9f6f2a9SGeneviève Bastien if (ret)
1315f9f6f2a9SGeneviève Bastien return ret;
1316f5a08cedSWang Nan return 0;
1317f5a08cedSWang Nan }
1318f5a08cedSWang Nan
cleanup_events(struct perf_session * session)13195141d735SWang Nan static void cleanup_events(struct perf_session *session)
13205141d735SWang Nan {
132163503dbaSJiri Olsa struct evlist *evlist = session->evlist;
132232dcd021SJiri Olsa struct evsel *evsel;
13235141d735SWang Nan
1324e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evlist, evsel) {
13255141d735SWang Nan struct evsel_priv *priv;
13265141d735SWang Nan
13275141d735SWang Nan priv = evsel->priv;
13285141d735SWang Nan bt_ctf_event_class_put(priv->event_class);
13295141d735SWang Nan zfree(&evsel->priv);
13305141d735SWang Nan }
13315141d735SWang Nan
1332c12995a5SJiri Olsa evlist__delete(evlist);
13335141d735SWang Nan session->evlist = NULL;
13345141d735SWang Nan }
13355141d735SWang Nan
setup_streams(struct ctf_writer * cw,struct perf_session * session)133690e129ffSSebastian Andrzej Siewior static int setup_streams(struct ctf_writer *cw, struct perf_session *session)
133790e129ffSSebastian Andrzej Siewior {
133890e129ffSSebastian Andrzej Siewior struct ctf_stream **stream;
133990e129ffSSebastian Andrzej Siewior struct perf_header *ph = &session->header;
134090e129ffSSebastian Andrzej Siewior int ncpus;
134190e129ffSSebastian Andrzej Siewior
134290e129ffSSebastian Andrzej Siewior /*
134390e129ffSSebastian Andrzej Siewior * Try to get the number of cpus used in the data file,
134490e129ffSSebastian Andrzej Siewior * if not present fallback to the MAX_CPUS.
134590e129ffSSebastian Andrzej Siewior */
134690e129ffSSebastian Andrzej Siewior ncpus = ph->env.nr_cpus_avail ?: MAX_CPUS;
134790e129ffSSebastian Andrzej Siewior
134890e129ffSSebastian Andrzej Siewior stream = zalloc(sizeof(*stream) * ncpus);
134990e129ffSSebastian Andrzej Siewior if (!stream) {
135090e129ffSSebastian Andrzej Siewior pr_err("Failed to allocate streams.\n");
135190e129ffSSebastian Andrzej Siewior return -ENOMEM;
135290e129ffSSebastian Andrzej Siewior }
135390e129ffSSebastian Andrzej Siewior
135490e129ffSSebastian Andrzej Siewior cw->stream = stream;
135590e129ffSSebastian Andrzej Siewior cw->stream_cnt = ncpus;
135690e129ffSSebastian Andrzej Siewior return 0;
135790e129ffSSebastian Andrzej Siewior }
135890e129ffSSebastian Andrzej Siewior
free_streams(struct ctf_writer * cw)135990e129ffSSebastian Andrzej Siewior static void free_streams(struct ctf_writer *cw)
136090e129ffSSebastian Andrzej Siewior {
136190e129ffSSebastian Andrzej Siewior int cpu;
136290e129ffSSebastian Andrzej Siewior
136390e129ffSSebastian Andrzej Siewior for (cpu = 0; cpu < cw->stream_cnt; cpu++)
136490e129ffSSebastian Andrzej Siewior ctf_stream__delete(cw->stream[cpu]);
136590e129ffSSebastian Andrzej Siewior
1366d8f9da24SArnaldo Carvalho de Melo zfree(&cw->stream);
136790e129ffSSebastian Andrzej Siewior }
136890e129ffSSebastian Andrzej Siewior
ctf_writer__setup_env(struct ctf_writer * cw,struct perf_session * session)1369edbe9817SJiri Olsa static int ctf_writer__setup_env(struct ctf_writer *cw,
1370edbe9817SJiri Olsa struct perf_session *session)
1371edbe9817SJiri Olsa {
1372edbe9817SJiri Olsa struct perf_header *header = &session->header;
1373edbe9817SJiri Olsa struct bt_ctf_writer *writer = cw->writer;
1374edbe9817SJiri Olsa
1375edbe9817SJiri Olsa #define ADD(__n, __v) \
1376edbe9817SJiri Olsa do { \
1377edbe9817SJiri Olsa if (bt_ctf_writer_add_environment_field(writer, __n, __v)) \
1378edbe9817SJiri Olsa return -1; \
1379edbe9817SJiri Olsa } while (0)
1380edbe9817SJiri Olsa
1381edbe9817SJiri Olsa ADD("host", header->env.hostname);
1382edbe9817SJiri Olsa ADD("sysname", "Linux");
1383edbe9817SJiri Olsa ADD("release", header->env.os_release);
1384edbe9817SJiri Olsa ADD("version", header->env.version);
1385edbe9817SJiri Olsa ADD("machine", header->env.arch);
1386edbe9817SJiri Olsa ADD("domain", "kernel");
1387edbe9817SJiri Olsa ADD("tracer_name", "perf");
1388edbe9817SJiri Olsa
1389edbe9817SJiri Olsa #undef ADD
1390edbe9817SJiri Olsa return 0;
1391edbe9817SJiri Olsa }
1392edbe9817SJiri Olsa
ctf_writer__setup_clock(struct ctf_writer * cw,struct perf_session * session,bool tod)139388371c58SJiri Olsa static int ctf_writer__setup_clock(struct ctf_writer *cw,
139488371c58SJiri Olsa struct perf_session *session,
139588371c58SJiri Olsa bool tod)
1396edbe9817SJiri Olsa {
1397edbe9817SJiri Olsa struct bt_ctf_clock *clock = cw->clock;
139888371c58SJiri Olsa const char *desc = "perf clock";
139988371c58SJiri Olsa int64_t offset = 0;
1400edbe9817SJiri Olsa
140188371c58SJiri Olsa if (tod) {
140288371c58SJiri Olsa struct perf_env *env = &session->header.env;
140388371c58SJiri Olsa
140488371c58SJiri Olsa if (!env->clock.enabled) {
140588371c58SJiri Olsa pr_err("Can't provide --tod time, missing clock data. "
140688371c58SJiri Olsa "Please record with -k/--clockid option.\n");
140788371c58SJiri Olsa return -1;
140888371c58SJiri Olsa }
140988371c58SJiri Olsa
141088371c58SJiri Olsa desc = clockid_name(env->clock.clockid);
141188371c58SJiri Olsa offset = env->clock.tod_ns - env->clock.clockid_ns;
141288371c58SJiri Olsa }
1413edbe9817SJiri Olsa
1414edbe9817SJiri Olsa #define SET(__n, __v) \
1415edbe9817SJiri Olsa do { \
1416edbe9817SJiri Olsa if (bt_ctf_clock_set_##__n(clock, __v)) \
1417edbe9817SJiri Olsa return -1; \
1418edbe9817SJiri Olsa } while (0)
1419edbe9817SJiri Olsa
1420edbe9817SJiri Olsa SET(frequency, 1000000000);
142188371c58SJiri Olsa SET(offset, offset);
142288371c58SJiri Olsa SET(description, desc);
1423edbe9817SJiri Olsa SET(precision, 10);
1424edbe9817SJiri Olsa SET(is_absolute, 0);
1425edbe9817SJiri Olsa
1426edbe9817SJiri Olsa #undef SET
1427edbe9817SJiri Olsa return 0;
1428edbe9817SJiri Olsa }
1429edbe9817SJiri Olsa
create_int_type(int size,bool sign,bool hex)1430edbe9817SJiri Olsa static struct bt_ctf_field_type *create_int_type(int size, bool sign, bool hex)
1431edbe9817SJiri Olsa {
1432edbe9817SJiri Olsa struct bt_ctf_field_type *type;
1433edbe9817SJiri Olsa
1434edbe9817SJiri Olsa type = bt_ctf_field_type_integer_create(size);
1435edbe9817SJiri Olsa if (!type)
1436edbe9817SJiri Olsa return NULL;
1437edbe9817SJiri Olsa
1438edbe9817SJiri Olsa if (sign &&
1439edbe9817SJiri Olsa bt_ctf_field_type_integer_set_signed(type, 1))
1440edbe9817SJiri Olsa goto err;
1441edbe9817SJiri Olsa
1442edbe9817SJiri Olsa if (hex &&
1443edbe9817SJiri Olsa bt_ctf_field_type_integer_set_base(type, BT_CTF_INTEGER_BASE_HEXADECIMAL))
1444edbe9817SJiri Olsa goto err;
1445edbe9817SJiri Olsa
14464e88118cSIlya Leoshkevich #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
1447f8dd2d5fSWang Nan bt_ctf_field_type_set_byte_order(type, BT_CTF_BYTE_ORDER_BIG_ENDIAN);
1448f8dd2d5fSWang Nan #else
1449f8dd2d5fSWang Nan bt_ctf_field_type_set_byte_order(type, BT_CTF_BYTE_ORDER_LITTLE_ENDIAN);
1450f8dd2d5fSWang Nan #endif
1451f8dd2d5fSWang Nan
1452edbe9817SJiri Olsa pr2("Created type: INTEGER %d-bit %ssigned %s\n",
1453edbe9817SJiri Olsa size, sign ? "un" : "", hex ? "hex" : "");
1454edbe9817SJiri Olsa return type;
1455edbe9817SJiri Olsa
1456edbe9817SJiri Olsa err:
1457edbe9817SJiri Olsa bt_ctf_field_type_put(type);
1458edbe9817SJiri Olsa return NULL;
1459edbe9817SJiri Olsa }
1460edbe9817SJiri Olsa
ctf_writer__cleanup_data(struct ctf_writer * cw)1461edbe9817SJiri Olsa static void ctf_writer__cleanup_data(struct ctf_writer *cw)
1462edbe9817SJiri Olsa {
1463edbe9817SJiri Olsa unsigned int i;
1464edbe9817SJiri Olsa
1465edbe9817SJiri Olsa for (i = 0; i < ARRAY_SIZE(cw->data.array); i++)
1466edbe9817SJiri Olsa bt_ctf_field_type_put(cw->data.array[i]);
1467edbe9817SJiri Olsa }
1468edbe9817SJiri Olsa
ctf_writer__init_data(struct ctf_writer * cw)1469edbe9817SJiri Olsa static int ctf_writer__init_data(struct ctf_writer *cw)
1470edbe9817SJiri Olsa {
1471edbe9817SJiri Olsa #define CREATE_INT_TYPE(type, size, sign, hex) \
1472edbe9817SJiri Olsa do { \
1473edbe9817SJiri Olsa (type) = create_int_type(size, sign, hex); \
1474edbe9817SJiri Olsa if (!(type)) \
1475edbe9817SJiri Olsa goto err; \
1476edbe9817SJiri Olsa } while (0)
1477edbe9817SJiri Olsa
1478edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.s64, 64, true, false);
1479edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.u64, 64, false, false);
1480edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.s32, 32, true, false);
1481edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.u32, 32, false, false);
148226812d46SWang Nan CREATE_INT_TYPE(cw->data.u32_hex, 32, false, true);
1483edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true);
1484edbe9817SJiri Olsa
1485edbe9817SJiri Olsa cw->data.string = bt_ctf_field_type_string_create();
1486edbe9817SJiri Olsa if (cw->data.string)
1487edbe9817SJiri Olsa return 0;
1488edbe9817SJiri Olsa
1489edbe9817SJiri Olsa err:
1490edbe9817SJiri Olsa ctf_writer__cleanup_data(cw);
1491edbe9817SJiri Olsa pr_err("Failed to create data types.\n");
1492edbe9817SJiri Olsa return -1;
1493edbe9817SJiri Olsa }
1494edbe9817SJiri Olsa
ctf_writer__cleanup(struct ctf_writer * cw)1495edbe9817SJiri Olsa static void ctf_writer__cleanup(struct ctf_writer *cw)
1496edbe9817SJiri Olsa {
1497edbe9817SJiri Olsa ctf_writer__cleanup_data(cw);
1498edbe9817SJiri Olsa
1499edbe9817SJiri Olsa bt_ctf_clock_put(cw->clock);
150090e129ffSSebastian Andrzej Siewior free_streams(cw);
1501edbe9817SJiri Olsa bt_ctf_stream_class_put(cw->stream_class);
1502edbe9817SJiri Olsa bt_ctf_writer_put(cw->writer);
1503edbe9817SJiri Olsa
1504edbe9817SJiri Olsa /* and NULL all the pointers */
1505edbe9817SJiri Olsa memset(cw, 0, sizeof(*cw));
1506edbe9817SJiri Olsa }
1507edbe9817SJiri Olsa
ctf_writer__init(struct ctf_writer * cw,const char * path,struct perf_session * session,bool tod)150888371c58SJiri Olsa static int ctf_writer__init(struct ctf_writer *cw, const char *path,
150988371c58SJiri Olsa struct perf_session *session, bool tod)
1510edbe9817SJiri Olsa {
1511edbe9817SJiri Olsa struct bt_ctf_writer *writer;
1512edbe9817SJiri Olsa struct bt_ctf_stream_class *stream_class;
1513edbe9817SJiri Olsa struct bt_ctf_clock *clock;
151490e129ffSSebastian Andrzej Siewior struct bt_ctf_field_type *pkt_ctx_type;
151590e129ffSSebastian Andrzej Siewior int ret;
1516edbe9817SJiri Olsa
1517edbe9817SJiri Olsa /* CTF writer */
1518edbe9817SJiri Olsa writer = bt_ctf_writer_create(path);
1519edbe9817SJiri Olsa if (!writer)
1520edbe9817SJiri Olsa goto err;
1521edbe9817SJiri Olsa
1522edbe9817SJiri Olsa cw->writer = writer;
1523edbe9817SJiri Olsa
1524edbe9817SJiri Olsa /* CTF clock */
1525edbe9817SJiri Olsa clock = bt_ctf_clock_create("perf_clock");
1526edbe9817SJiri Olsa if (!clock) {
1527edbe9817SJiri Olsa pr("Failed to create CTF clock.\n");
1528edbe9817SJiri Olsa goto err_cleanup;
1529edbe9817SJiri Olsa }
1530edbe9817SJiri Olsa
1531edbe9817SJiri Olsa cw->clock = clock;
1532edbe9817SJiri Olsa
153388371c58SJiri Olsa if (ctf_writer__setup_clock(cw, session, tod)) {
1534edbe9817SJiri Olsa pr("Failed to setup CTF clock.\n");
1535edbe9817SJiri Olsa goto err_cleanup;
1536edbe9817SJiri Olsa }
1537edbe9817SJiri Olsa
1538edbe9817SJiri Olsa /* CTF stream class */
1539edbe9817SJiri Olsa stream_class = bt_ctf_stream_class_create("perf_stream");
1540edbe9817SJiri Olsa if (!stream_class) {
1541edbe9817SJiri Olsa pr("Failed to create CTF stream class.\n");
1542edbe9817SJiri Olsa goto err_cleanup;
1543edbe9817SJiri Olsa }
1544edbe9817SJiri Olsa
1545edbe9817SJiri Olsa cw->stream_class = stream_class;
1546edbe9817SJiri Olsa
1547edbe9817SJiri Olsa /* CTF clock stream setup */
1548edbe9817SJiri Olsa if (bt_ctf_stream_class_set_clock(stream_class, clock)) {
1549edbe9817SJiri Olsa pr("Failed to assign CTF clock to stream class.\n");
1550edbe9817SJiri Olsa goto err_cleanup;
1551edbe9817SJiri Olsa }
1552edbe9817SJiri Olsa
1553edbe9817SJiri Olsa if (ctf_writer__init_data(cw))
1554edbe9817SJiri Olsa goto err_cleanup;
1555edbe9817SJiri Olsa
155690e129ffSSebastian Andrzej Siewior /* Add cpu_id for packet context */
155790e129ffSSebastian Andrzej Siewior pkt_ctx_type = bt_ctf_stream_class_get_packet_context_type(stream_class);
155890e129ffSSebastian Andrzej Siewior if (!pkt_ctx_type)
1559edbe9817SJiri Olsa goto err_cleanup;
1560edbe9817SJiri Olsa
156190e129ffSSebastian Andrzej Siewior ret = bt_ctf_field_type_structure_add_field(pkt_ctx_type, cw->data.u32, "cpu_id");
156290e129ffSSebastian Andrzej Siewior bt_ctf_field_type_put(pkt_ctx_type);
156390e129ffSSebastian Andrzej Siewior if (ret)
156490e129ffSSebastian Andrzej Siewior goto err_cleanup;
1565edbe9817SJiri Olsa
1566edbe9817SJiri Olsa /* CTF clock writer setup */
1567edbe9817SJiri Olsa if (bt_ctf_writer_add_clock(writer, clock)) {
1568edbe9817SJiri Olsa pr("Failed to assign CTF clock to writer.\n");
1569edbe9817SJiri Olsa goto err_cleanup;
1570edbe9817SJiri Olsa }
1571edbe9817SJiri Olsa
1572edbe9817SJiri Olsa return 0;
1573edbe9817SJiri Olsa
1574edbe9817SJiri Olsa err_cleanup:
1575edbe9817SJiri Olsa ctf_writer__cleanup(cw);
1576edbe9817SJiri Olsa err:
1577edbe9817SJiri Olsa pr_err("Failed to setup CTF writer.\n");
1578edbe9817SJiri Olsa return -1;
1579edbe9817SJiri Olsa }
1580edbe9817SJiri Olsa
ctf_writer__flush_streams(struct ctf_writer * cw)158190e129ffSSebastian Andrzej Siewior static int ctf_writer__flush_streams(struct ctf_writer *cw)
158290e129ffSSebastian Andrzej Siewior {
158390e129ffSSebastian Andrzej Siewior int cpu, ret = 0;
158490e129ffSSebastian Andrzej Siewior
158590e129ffSSebastian Andrzej Siewior for (cpu = 0; cpu < cw->stream_cnt && !ret; cpu++)
158690e129ffSSebastian Andrzej Siewior ret = ctf_stream__flush(cw->stream[cpu]);
158790e129ffSSebastian Andrzej Siewior
158890e129ffSSebastian Andrzej Siewior return ret;
158990e129ffSSebastian Andrzej Siewior }
159090e129ffSSebastian Andrzej Siewior
convert__config(const char * var,const char * value,void * cb)15918fa46753SJiri Olsa static int convert__config(const char *var, const char *value, void *cb)
15928fa46753SJiri Olsa {
15938fa46753SJiri Olsa struct convert *c = cb;
15948fa46753SJiri Olsa
159525ce4bb8SArnaldo Carvalho de Melo if (!strcmp(var, "convert.queue-size"))
159625ce4bb8SArnaldo Carvalho de Melo return perf_config_u64(&c->queue_size, var, value);
15978fa46753SJiri Olsa
1598b8cbb349SWang Nan return 0;
15998fa46753SJiri Olsa }
16008fa46753SJiri Olsa
bt_convert__perf2ctf(const char * input,const char * path,struct perf_data_convert_opts * opts)16013275f68eSWang Nan int bt_convert__perf2ctf(const char *input, const char *path,
16023275f68eSWang Nan struct perf_data_convert_opts *opts)
1603edbe9817SJiri Olsa {
1604edbe9817SJiri Olsa struct perf_session *session;
16058ceb41d7SJiri Olsa struct perf_data data = {
16062d4f2799SJiri Olsa .path = input,
1607edbe9817SJiri Olsa .mode = PERF_DATA_MODE_READ,
16083275f68eSWang Nan .force = opts->force,
1609edbe9817SJiri Olsa };
1610edbe9817SJiri Olsa struct convert c = {
1611edbe9817SJiri Olsa .tool = {
1612edbe9817SJiri Olsa .sample = process_sample_event,
1613edbe9817SJiri Olsa .mmap = perf_event__process_mmap,
1614edbe9817SJiri Olsa .mmap2 = perf_event__process_mmap2,
1615edbe9817SJiri Olsa .comm = perf_event__process_comm,
1616edbe9817SJiri Olsa .exit = perf_event__process_exit,
1617edbe9817SJiri Olsa .fork = perf_event__process_fork,
1618edbe9817SJiri Olsa .lost = perf_event__process_lost,
1619edbe9817SJiri Olsa .tracing_data = perf_event__process_tracing_data,
1620edbe9817SJiri Olsa .build_id = perf_event__process_build_id,
1621f3b3614aSHari Bathini .namespaces = perf_event__process_namespaces,
1622edbe9817SJiri Olsa .ordered_events = true,
1623edbe9817SJiri Olsa .ordering_requires_timestamps = true,
1624edbe9817SJiri Olsa },
1625edbe9817SJiri Olsa };
1626edbe9817SJiri Olsa struct ctf_writer *cw = &c.writer;
1627ecc4c561SArnaldo Carvalho de Melo int err;
1628edbe9817SJiri Olsa
1629ebccba3fSWang Nan if (opts->all) {
1630f5a08cedSWang Nan c.tool.comm = process_comm_event;
1631ebccba3fSWang Nan c.tool.exit = process_exit_event;
1632ebccba3fSWang Nan c.tool.fork = process_fork_event;
1633f9f6f2a9SGeneviève Bastien c.tool.mmap = process_mmap_event;
1634f9f6f2a9SGeneviève Bastien c.tool.mmap2 = process_mmap2_event;
1635ebccba3fSWang Nan }
1636f5a08cedSWang Nan
1637ecc4c561SArnaldo Carvalho de Melo err = perf_config(convert__config, &c);
1638ecc4c561SArnaldo Carvalho de Melo if (err)
1639ecc4c561SArnaldo Carvalho de Melo return err;
16408fa46753SJiri Olsa
1641ecc4c561SArnaldo Carvalho de Melo err = -1;
1642edbe9817SJiri Olsa /* perf.data session */
16432681bd85SNamhyung Kim session = perf_session__new(&data, &c.tool);
164488371c58SJiri Olsa if (IS_ERR(session))
164588371c58SJiri Olsa return PTR_ERR(session);
164688371c58SJiri Olsa
164788371c58SJiri Olsa /* CTF writer */
164888371c58SJiri Olsa if (ctf_writer__init(cw, path, session, opts->tod))
164988371c58SJiri Olsa goto free_session;
1650edbe9817SJiri Olsa
16518fa46753SJiri Olsa if (c.queue_size) {
16528fa46753SJiri Olsa ordered_events__set_alloc_size(&session->ordered_events,
16538fa46753SJiri Olsa c.queue_size);
16548fa46753SJiri Olsa }
16558fa46753SJiri Olsa
1656edbe9817SJiri Olsa /* CTF writer env/clock setup */
1657edbe9817SJiri Olsa if (ctf_writer__setup_env(cw, session))
165888371c58SJiri Olsa goto free_writer;
1659edbe9817SJiri Olsa
1660edbe9817SJiri Olsa /* CTF events setup */
1661edbe9817SJiri Olsa if (setup_events(cw, session))
166288371c58SJiri Olsa goto free_writer;
1663edbe9817SJiri Olsa
1664f5a08cedSWang Nan if (opts->all && setup_non_sample_events(cw, session))
166588371c58SJiri Olsa goto free_writer;
1666f5a08cedSWang Nan
166790e129ffSSebastian Andrzej Siewior if (setup_streams(cw, session))
166888371c58SJiri Olsa goto free_writer;
166990e129ffSSebastian Andrzej Siewior
1670b7b61cbeSArnaldo Carvalho de Melo err = perf_session__process_events(session);
1671edbe9817SJiri Olsa if (!err)
167290e129ffSSebastian Andrzej Siewior err = ctf_writer__flush_streams(cw);
1673c2141055SHe Kuang else
1674c2141055SHe Kuang pr_err("Error during conversion.\n");
1675edbe9817SJiri Olsa
1676edbe9817SJiri Olsa fprintf(stderr,
1677edbe9817SJiri Olsa "[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
16782d4f2799SJiri Olsa data.path, path);
1679edbe9817SJiri Olsa
1680edbe9817SJiri Olsa fprintf(stderr,
16818ee4c46cSWang Nan "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
1682edbe9817SJiri Olsa (double) c.events_size / 1024.0 / 1024.0,
1683edbe9817SJiri Olsa c.events_count);
1684edbe9817SJiri Olsa
16858ee4c46cSWang Nan if (!c.non_sample_count)
16868ee4c46cSWang Nan fprintf(stderr, ") ]\n");
16878ee4c46cSWang Nan else
16888ee4c46cSWang Nan fprintf(stderr, ", %" PRIu64 " non-samples) ]\n", c.non_sample_count);
16898ee4c46cSWang Nan
16905141d735SWang Nan cleanup_events(session);
1691c2141055SHe Kuang perf_session__delete(session);
1692c2141055SHe Kuang ctf_writer__cleanup(cw);
1693c2141055SHe Kuang
1694c2141055SHe Kuang return err;
1695c2141055SHe Kuang
1696edbe9817SJiri Olsa free_writer:
1697edbe9817SJiri Olsa ctf_writer__cleanup(cw);
169888371c58SJiri Olsa free_session:
169988371c58SJiri Olsa perf_session__delete(session);
1700c2141055SHe Kuang pr_err("Error during conversion setup.\n");
1701edbe9817SJiri Olsa return err;
1702edbe9817SJiri Olsa }
1703