1edbe9817SJiri Olsa /* 2edbe9817SJiri Olsa * CTF writing support via babeltrace. 3edbe9817SJiri Olsa * 4edbe9817SJiri Olsa * Copyright (C) 2014, Jiri Olsa <jolsa@redhat.com> 5edbe9817SJiri Olsa * Copyright (C) 2014, Sebastian Andrzej Siewior <bigeasy@linutronix.de> 6edbe9817SJiri Olsa * 7edbe9817SJiri Olsa * Released under the GPL v2. (and only v2, not any later version) 8edbe9817SJiri Olsa */ 9edbe9817SJiri Olsa 10edbe9817SJiri Olsa #include <linux/compiler.h> 11edbe9817SJiri Olsa #include <babeltrace/ctf-writer/writer.h> 12edbe9817SJiri Olsa #include <babeltrace/ctf-writer/clock.h> 13edbe9817SJiri Olsa #include <babeltrace/ctf-writer/stream.h> 14edbe9817SJiri Olsa #include <babeltrace/ctf-writer/event.h> 15edbe9817SJiri Olsa #include <babeltrace/ctf-writer/event-types.h> 16edbe9817SJiri Olsa #include <babeltrace/ctf-writer/event-fields.h> 17e0a7cce5SWang Nan #include <babeltrace/ctf-ir/utils.h> 18edbe9817SJiri Olsa #include <babeltrace/ctf/events.h> 19edbe9817SJiri Olsa #include <traceevent/event-parse.h> 20edbe9817SJiri Olsa #include "asm/bug.h" 21edbe9817SJiri Olsa #include "data-convert-bt.h" 22edbe9817SJiri Olsa #include "session.h" 23edbe9817SJiri Olsa #include "util.h" 24edbe9817SJiri Olsa #include "debug.h" 25edbe9817SJiri Olsa #include "tool.h" 26edbe9817SJiri Olsa #include "evlist.h" 27edbe9817SJiri Olsa #include "evsel.h" 28edbe9817SJiri Olsa #include "machine.h" 29edbe9817SJiri Olsa 30edbe9817SJiri Olsa #define pr_N(n, fmt, ...) \ 31edbe9817SJiri Olsa eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__) 32edbe9817SJiri Olsa 33edbe9817SJiri Olsa #define pr(fmt, ...) pr_N(1, pr_fmt(fmt), ##__VA_ARGS__) 34edbe9817SJiri Olsa #define pr2(fmt, ...) pr_N(2, pr_fmt(fmt), ##__VA_ARGS__) 35edbe9817SJiri Olsa 36edbe9817SJiri Olsa #define pr_time2(t, fmt, ...) pr_time_N(2, debug_data_convert, t, pr_fmt(fmt), ##__VA_ARGS__) 37edbe9817SJiri Olsa 38edbe9817SJiri Olsa struct evsel_priv { 39edbe9817SJiri Olsa struct bt_ctf_event_class *event_class; 40edbe9817SJiri Olsa }; 41edbe9817SJiri Olsa 4290e129ffSSebastian Andrzej Siewior #define MAX_CPUS 4096 4390e129ffSSebastian Andrzej Siewior 4490e129ffSSebastian Andrzej Siewior struct ctf_stream { 4590e129ffSSebastian Andrzej Siewior struct bt_ctf_stream *stream; 4690e129ffSSebastian Andrzej Siewior int cpu; 4789e5fa88SJiri Olsa u32 count; 4890e129ffSSebastian Andrzej Siewior }; 4990e129ffSSebastian Andrzej Siewior 50edbe9817SJiri Olsa struct ctf_writer { 51edbe9817SJiri Olsa /* writer primitives */ 52edbe9817SJiri Olsa struct bt_ctf_writer *writer; 5390e129ffSSebastian Andrzej Siewior struct ctf_stream **stream; 5490e129ffSSebastian Andrzej Siewior int stream_cnt; 55edbe9817SJiri Olsa struct bt_ctf_stream_class *stream_class; 56edbe9817SJiri Olsa struct bt_ctf_clock *clock; 57edbe9817SJiri Olsa 58edbe9817SJiri Olsa /* data types */ 59edbe9817SJiri Olsa union { 60edbe9817SJiri Olsa struct { 61edbe9817SJiri Olsa struct bt_ctf_field_type *s64; 62edbe9817SJiri Olsa struct bt_ctf_field_type *u64; 63edbe9817SJiri Olsa struct bt_ctf_field_type *s32; 64edbe9817SJiri Olsa struct bt_ctf_field_type *u32; 65edbe9817SJiri Olsa struct bt_ctf_field_type *string; 66edbe9817SJiri Olsa struct bt_ctf_field_type *u64_hex; 67edbe9817SJiri Olsa }; 68edbe9817SJiri Olsa struct bt_ctf_field_type *array[6]; 69edbe9817SJiri Olsa } data; 70edbe9817SJiri Olsa }; 71edbe9817SJiri Olsa 72edbe9817SJiri Olsa struct convert { 73edbe9817SJiri Olsa struct perf_tool tool; 74edbe9817SJiri Olsa struct ctf_writer writer; 75edbe9817SJiri Olsa 76edbe9817SJiri Olsa u64 events_size; 77edbe9817SJiri Olsa u64 events_count; 788fa46753SJiri Olsa 798fa46753SJiri Olsa /* Ordered events configured queue size. */ 808fa46753SJiri Olsa u64 queue_size; 81edbe9817SJiri Olsa }; 82edbe9817SJiri Olsa 83edbe9817SJiri Olsa static int value_set(struct bt_ctf_field_type *type, 84edbe9817SJiri Olsa struct bt_ctf_event *event, 85edbe9817SJiri Olsa const char *name, u64 val) 86edbe9817SJiri Olsa { 87edbe9817SJiri Olsa struct bt_ctf_field *field; 88edbe9817SJiri Olsa bool sign = bt_ctf_field_type_integer_get_signed(type); 89edbe9817SJiri Olsa int ret; 90edbe9817SJiri Olsa 91edbe9817SJiri Olsa field = bt_ctf_field_create(type); 92edbe9817SJiri Olsa if (!field) { 93edbe9817SJiri Olsa pr_err("failed to create a field %s\n", name); 94edbe9817SJiri Olsa return -1; 95edbe9817SJiri Olsa } 96edbe9817SJiri Olsa 97edbe9817SJiri Olsa if (sign) { 98edbe9817SJiri Olsa ret = bt_ctf_field_signed_integer_set_value(field, val); 99edbe9817SJiri Olsa if (ret) { 100edbe9817SJiri Olsa pr_err("failed to set field value %s\n", name); 101edbe9817SJiri Olsa goto err; 102edbe9817SJiri Olsa } 103edbe9817SJiri Olsa } else { 104edbe9817SJiri Olsa ret = bt_ctf_field_unsigned_integer_set_value(field, val); 105edbe9817SJiri Olsa if (ret) { 106edbe9817SJiri Olsa pr_err("failed to set field value %s\n", name); 107edbe9817SJiri Olsa goto err; 108edbe9817SJiri Olsa } 109edbe9817SJiri Olsa } 110edbe9817SJiri Olsa 111edbe9817SJiri Olsa ret = bt_ctf_event_set_payload(event, name, field); 112edbe9817SJiri Olsa if (ret) { 113edbe9817SJiri Olsa pr_err("failed to set payload %s\n", name); 114edbe9817SJiri Olsa goto err; 115edbe9817SJiri Olsa } 116edbe9817SJiri Olsa 117edbe9817SJiri Olsa pr2(" SET [%s = %" PRIu64 "]\n", name, val); 118edbe9817SJiri Olsa 119edbe9817SJiri Olsa err: 120edbe9817SJiri Olsa bt_ctf_field_put(field); 121edbe9817SJiri Olsa return ret; 122edbe9817SJiri Olsa } 123edbe9817SJiri Olsa 124edbe9817SJiri Olsa #define __FUNC_VALUE_SET(_name, _val_type) \ 125edbe9817SJiri Olsa static __maybe_unused int value_set_##_name(struct ctf_writer *cw, \ 126edbe9817SJiri Olsa struct bt_ctf_event *event, \ 127edbe9817SJiri Olsa const char *name, \ 128edbe9817SJiri Olsa _val_type val) \ 129edbe9817SJiri Olsa { \ 130edbe9817SJiri Olsa struct bt_ctf_field_type *type = cw->data._name; \ 131edbe9817SJiri Olsa return value_set(type, event, name, (u64) val); \ 132edbe9817SJiri Olsa } 133edbe9817SJiri Olsa 134edbe9817SJiri Olsa #define FUNC_VALUE_SET(_name) __FUNC_VALUE_SET(_name, _name) 135edbe9817SJiri Olsa 136edbe9817SJiri Olsa FUNC_VALUE_SET(s32) 137edbe9817SJiri Olsa FUNC_VALUE_SET(u32) 138edbe9817SJiri Olsa FUNC_VALUE_SET(s64) 139edbe9817SJiri Olsa FUNC_VALUE_SET(u64) 140edbe9817SJiri Olsa __FUNC_VALUE_SET(u64_hex, u64) 141edbe9817SJiri Olsa 14269364727SSebastian Andrzej Siewior static struct bt_ctf_field_type* 14369364727SSebastian Andrzej Siewior get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field) 14469364727SSebastian Andrzej Siewior { 14569364727SSebastian Andrzej Siewior unsigned long flags = field->flags; 14669364727SSebastian Andrzej Siewior 14769364727SSebastian Andrzej Siewior if (flags & FIELD_IS_STRING) 14869364727SSebastian Andrzej Siewior return cw->data.string; 14969364727SSebastian Andrzej Siewior 15069364727SSebastian Andrzej Siewior if (!(flags & FIELD_IS_SIGNED)) { 15169364727SSebastian Andrzej Siewior /* unsigned long are mostly pointers */ 15269364727SSebastian Andrzej Siewior if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER) 15369364727SSebastian Andrzej Siewior return cw->data.u64_hex; 15469364727SSebastian Andrzej Siewior } 15569364727SSebastian Andrzej Siewior 15669364727SSebastian Andrzej Siewior if (flags & FIELD_IS_SIGNED) { 15769364727SSebastian Andrzej Siewior if (field->size == 8) 15869364727SSebastian Andrzej Siewior return cw->data.s64; 15969364727SSebastian Andrzej Siewior else 16069364727SSebastian Andrzej Siewior return cw->data.s32; 16169364727SSebastian Andrzej Siewior } 16269364727SSebastian Andrzej Siewior 16369364727SSebastian Andrzej Siewior if (field->size == 8) 16469364727SSebastian Andrzej Siewior return cw->data.u64; 16569364727SSebastian Andrzej Siewior else 16669364727SSebastian Andrzej Siewior return cw->data.u32; 16769364727SSebastian Andrzej Siewior } 16869364727SSebastian Andrzej Siewior 169*d4ae4213SWang Nan static unsigned long long adjust_signedness(unsigned long long value_int, int size) 170*d4ae4213SWang Nan { 171*d4ae4213SWang Nan unsigned long long value_mask; 172*d4ae4213SWang Nan 173*d4ae4213SWang Nan /* 174*d4ae4213SWang Nan * value_mask = (1 << (size * 8 - 1)) - 1. 175*d4ae4213SWang Nan * Directly set value_mask for code readers. 176*d4ae4213SWang Nan */ 177*d4ae4213SWang Nan switch (size) { 178*d4ae4213SWang Nan case 1: 179*d4ae4213SWang Nan value_mask = 0x7fULL; 180*d4ae4213SWang Nan break; 181*d4ae4213SWang Nan case 2: 182*d4ae4213SWang Nan value_mask = 0x7fffULL; 183*d4ae4213SWang Nan break; 184*d4ae4213SWang Nan case 4: 185*d4ae4213SWang Nan value_mask = 0x7fffffffULL; 186*d4ae4213SWang Nan break; 187*d4ae4213SWang Nan case 8: 188*d4ae4213SWang Nan /* 189*d4ae4213SWang Nan * For 64 bit value, return it self. There is no need 190*d4ae4213SWang Nan * to fill high bit. 191*d4ae4213SWang Nan */ 192*d4ae4213SWang Nan /* Fall through */ 193*d4ae4213SWang Nan default: 194*d4ae4213SWang Nan /* BUG! */ 195*d4ae4213SWang Nan return value_int; 196*d4ae4213SWang Nan } 197*d4ae4213SWang Nan 198*d4ae4213SWang Nan /* If it is a positive value, don't adjust. */ 199*d4ae4213SWang Nan if ((value_int & (~0ULL - value_mask)) == 0) 200*d4ae4213SWang Nan return value_int; 201*d4ae4213SWang Nan 202*d4ae4213SWang Nan /* Fill upper part of value_int with 1 to make it a negative long long. */ 203*d4ae4213SWang Nan return (value_int & value_mask) | ~value_mask; 204*d4ae4213SWang Nan } 205*d4ae4213SWang Nan 20669364727SSebastian Andrzej Siewior static int add_tracepoint_field_value(struct ctf_writer *cw, 20769364727SSebastian Andrzej Siewior struct bt_ctf_event_class *event_class, 20869364727SSebastian Andrzej Siewior struct bt_ctf_event *event, 20969364727SSebastian Andrzej Siewior struct perf_sample *sample, 21069364727SSebastian Andrzej Siewior struct format_field *fmtf) 21169364727SSebastian Andrzej Siewior { 21269364727SSebastian Andrzej Siewior struct bt_ctf_field_type *type; 21369364727SSebastian Andrzej Siewior struct bt_ctf_field *array_field; 21469364727SSebastian Andrzej Siewior struct bt_ctf_field *field; 21569364727SSebastian Andrzej Siewior const char *name = fmtf->name; 21669364727SSebastian Andrzej Siewior void *data = sample->raw_data; 21769364727SSebastian Andrzej Siewior unsigned long flags = fmtf->flags; 21869364727SSebastian Andrzej Siewior unsigned int n_items; 21969364727SSebastian Andrzej Siewior unsigned int i; 22069364727SSebastian Andrzej Siewior unsigned int offset; 22169364727SSebastian Andrzej Siewior unsigned int len; 22269364727SSebastian Andrzej Siewior int ret; 22369364727SSebastian Andrzej Siewior 224e0a7cce5SWang Nan name = fmtf->alias; 22569364727SSebastian Andrzej Siewior offset = fmtf->offset; 22669364727SSebastian Andrzej Siewior len = fmtf->size; 22769364727SSebastian Andrzej Siewior if (flags & FIELD_IS_STRING) 22869364727SSebastian Andrzej Siewior flags &= ~FIELD_IS_ARRAY; 22969364727SSebastian Andrzej Siewior 23069364727SSebastian Andrzej Siewior if (flags & FIELD_IS_DYNAMIC) { 23169364727SSebastian Andrzej Siewior unsigned long long tmp_val; 23269364727SSebastian Andrzej Siewior 23369364727SSebastian Andrzej Siewior tmp_val = pevent_read_number(fmtf->event->pevent, 23469364727SSebastian Andrzej Siewior data + offset, len); 23569364727SSebastian Andrzej Siewior offset = tmp_val; 23669364727SSebastian Andrzej Siewior len = offset >> 16; 23769364727SSebastian Andrzej Siewior offset &= 0xffff; 23869364727SSebastian Andrzej Siewior } 23969364727SSebastian Andrzej Siewior 24069364727SSebastian Andrzej Siewior if (flags & FIELD_IS_ARRAY) { 24169364727SSebastian Andrzej Siewior 24269364727SSebastian Andrzej Siewior type = bt_ctf_event_class_get_field_by_name( 24369364727SSebastian Andrzej Siewior event_class, name); 24469364727SSebastian Andrzej Siewior array_field = bt_ctf_field_create(type); 24569364727SSebastian Andrzej Siewior bt_ctf_field_type_put(type); 24669364727SSebastian Andrzej Siewior if (!array_field) { 24769364727SSebastian Andrzej Siewior pr_err("Failed to create array type %s\n", name); 24869364727SSebastian Andrzej Siewior return -1; 24969364727SSebastian Andrzej Siewior } 25069364727SSebastian Andrzej Siewior 25169364727SSebastian Andrzej Siewior len = fmtf->size / fmtf->arraylen; 25269364727SSebastian Andrzej Siewior n_items = fmtf->arraylen; 25369364727SSebastian Andrzej Siewior } else { 25469364727SSebastian Andrzej Siewior n_items = 1; 25569364727SSebastian Andrzej Siewior array_field = NULL; 25669364727SSebastian Andrzej Siewior } 25769364727SSebastian Andrzej Siewior 25869364727SSebastian Andrzej Siewior type = get_tracepoint_field_type(cw, fmtf); 25969364727SSebastian Andrzej Siewior 26069364727SSebastian Andrzej Siewior for (i = 0; i < n_items; i++) { 26169364727SSebastian Andrzej Siewior if (flags & FIELD_IS_ARRAY) 26269364727SSebastian Andrzej Siewior field = bt_ctf_field_array_get_field(array_field, i); 26369364727SSebastian Andrzej Siewior else 26469364727SSebastian Andrzej Siewior field = bt_ctf_field_create(type); 26569364727SSebastian Andrzej Siewior 26669364727SSebastian Andrzej Siewior if (!field) { 26769364727SSebastian Andrzej Siewior pr_err("failed to create a field %s\n", name); 26869364727SSebastian Andrzej Siewior return -1; 26969364727SSebastian Andrzej Siewior } 27069364727SSebastian Andrzej Siewior 27169364727SSebastian Andrzej Siewior if (flags & FIELD_IS_STRING) 27269364727SSebastian Andrzej Siewior ret = bt_ctf_field_string_set_value(field, 27369364727SSebastian Andrzej Siewior data + offset + i * len); 274*d4ae4213SWang Nan else { 275*d4ae4213SWang Nan unsigned long long value_int; 276*d4ae4213SWang Nan 277*d4ae4213SWang Nan value_int = pevent_read_number( 278*d4ae4213SWang Nan fmtf->event->pevent, 279*d4ae4213SWang Nan data + offset + i * len, len); 280*d4ae4213SWang Nan 281*d4ae4213SWang Nan if (!(flags & FIELD_IS_SIGNED)) 28269364727SSebastian Andrzej Siewior ret = bt_ctf_field_unsigned_integer_set_value( 28369364727SSebastian Andrzej Siewior field, value_int); 28469364727SSebastian Andrzej Siewior else 28569364727SSebastian Andrzej Siewior ret = bt_ctf_field_signed_integer_set_value( 286*d4ae4213SWang Nan field, adjust_signedness(value_int, len)); 287*d4ae4213SWang Nan } 288*d4ae4213SWang Nan 28969364727SSebastian Andrzej Siewior if (ret) { 29069364727SSebastian Andrzej Siewior pr_err("failed to set file value %s\n", name); 29169364727SSebastian Andrzej Siewior goto err_put_field; 29269364727SSebastian Andrzej Siewior } 29369364727SSebastian Andrzej Siewior if (!(flags & FIELD_IS_ARRAY)) { 29469364727SSebastian Andrzej Siewior ret = bt_ctf_event_set_payload(event, name, field); 29569364727SSebastian Andrzej Siewior if (ret) { 29669364727SSebastian Andrzej Siewior pr_err("failed to set payload %s\n", name); 29769364727SSebastian Andrzej Siewior goto err_put_field; 29869364727SSebastian Andrzej Siewior } 29969364727SSebastian Andrzej Siewior } 30069364727SSebastian Andrzej Siewior bt_ctf_field_put(field); 30169364727SSebastian Andrzej Siewior } 30269364727SSebastian Andrzej Siewior if (flags & FIELD_IS_ARRAY) { 30369364727SSebastian Andrzej Siewior ret = bt_ctf_event_set_payload(event, name, array_field); 30469364727SSebastian Andrzej Siewior if (ret) { 30569364727SSebastian Andrzej Siewior pr_err("Failed add payload array %s\n", name); 30669364727SSebastian Andrzej Siewior return -1; 30769364727SSebastian Andrzej Siewior } 30869364727SSebastian Andrzej Siewior bt_ctf_field_put(array_field); 30969364727SSebastian Andrzej Siewior } 31069364727SSebastian Andrzej Siewior return 0; 31169364727SSebastian Andrzej Siewior 31269364727SSebastian Andrzej Siewior err_put_field: 31369364727SSebastian Andrzej Siewior bt_ctf_field_put(field); 31469364727SSebastian Andrzej Siewior return -1; 31569364727SSebastian Andrzej Siewior } 31669364727SSebastian Andrzej Siewior 31769364727SSebastian Andrzej Siewior static int add_tracepoint_fields_values(struct ctf_writer *cw, 31869364727SSebastian Andrzej Siewior struct bt_ctf_event_class *event_class, 31969364727SSebastian Andrzej Siewior struct bt_ctf_event *event, 32069364727SSebastian Andrzej Siewior struct format_field *fields, 32169364727SSebastian Andrzej Siewior struct perf_sample *sample) 32269364727SSebastian Andrzej Siewior { 32369364727SSebastian Andrzej Siewior struct format_field *field; 32469364727SSebastian Andrzej Siewior int ret; 32569364727SSebastian Andrzej Siewior 32669364727SSebastian Andrzej Siewior for (field = fields; field; field = field->next) { 32769364727SSebastian Andrzej Siewior ret = add_tracepoint_field_value(cw, event_class, event, sample, 32869364727SSebastian Andrzej Siewior field); 32969364727SSebastian Andrzej Siewior if (ret) 33069364727SSebastian Andrzej Siewior return -1; 33169364727SSebastian Andrzej Siewior } 33269364727SSebastian Andrzej Siewior return 0; 33369364727SSebastian Andrzej Siewior } 33469364727SSebastian Andrzej Siewior 33569364727SSebastian Andrzej Siewior static int add_tracepoint_values(struct ctf_writer *cw, 33669364727SSebastian Andrzej Siewior struct bt_ctf_event_class *event_class, 33769364727SSebastian Andrzej Siewior struct bt_ctf_event *event, 33869364727SSebastian Andrzej Siewior struct perf_evsel *evsel, 33969364727SSebastian Andrzej Siewior struct perf_sample *sample) 34069364727SSebastian Andrzej Siewior { 34169364727SSebastian Andrzej Siewior struct format_field *common_fields = evsel->tp_format->format.common_fields; 34269364727SSebastian Andrzej Siewior struct format_field *fields = evsel->tp_format->format.fields; 34369364727SSebastian Andrzej Siewior int ret; 34469364727SSebastian Andrzej Siewior 34569364727SSebastian Andrzej Siewior ret = add_tracepoint_fields_values(cw, event_class, event, 34669364727SSebastian Andrzej Siewior common_fields, sample); 34769364727SSebastian Andrzej Siewior if (!ret) 34869364727SSebastian Andrzej Siewior ret = add_tracepoint_fields_values(cw, event_class, event, 34969364727SSebastian Andrzej Siewior fields, sample); 35069364727SSebastian Andrzej Siewior 35169364727SSebastian Andrzej Siewior return ret; 35269364727SSebastian Andrzej Siewior } 35369364727SSebastian Andrzej Siewior 354edbe9817SJiri Olsa static int add_generic_values(struct ctf_writer *cw, 355edbe9817SJiri Olsa struct bt_ctf_event *event, 356edbe9817SJiri Olsa struct perf_evsel *evsel, 357edbe9817SJiri Olsa struct perf_sample *sample) 358edbe9817SJiri Olsa { 359edbe9817SJiri Olsa u64 type = evsel->attr.sample_type; 360edbe9817SJiri Olsa int ret; 361edbe9817SJiri Olsa 362edbe9817SJiri Olsa /* 363edbe9817SJiri Olsa * missing: 364edbe9817SJiri Olsa * PERF_SAMPLE_TIME - not needed as we have it in 365edbe9817SJiri Olsa * ctf event header 366edbe9817SJiri Olsa * PERF_SAMPLE_READ - TODO 367edbe9817SJiri Olsa * PERF_SAMPLE_CALLCHAIN - TODO 368edbe9817SJiri Olsa * PERF_SAMPLE_RAW - tracepoint fields are handled separately 369edbe9817SJiri Olsa * PERF_SAMPLE_BRANCH_STACK - TODO 370edbe9817SJiri Olsa * PERF_SAMPLE_REGS_USER - TODO 371edbe9817SJiri Olsa * PERF_SAMPLE_STACK_USER - TODO 372edbe9817SJiri Olsa */ 373edbe9817SJiri Olsa 374edbe9817SJiri Olsa if (type & PERF_SAMPLE_IP) { 37554cf776aSSebastian Andrzej Siewior ret = value_set_u64_hex(cw, event, "perf_ip", sample->ip); 376edbe9817SJiri Olsa if (ret) 377edbe9817SJiri Olsa return -1; 378edbe9817SJiri Olsa } 379edbe9817SJiri Olsa 380edbe9817SJiri Olsa if (type & PERF_SAMPLE_TID) { 38154cf776aSSebastian Andrzej Siewior ret = value_set_s32(cw, event, "perf_tid", sample->tid); 382edbe9817SJiri Olsa if (ret) 383edbe9817SJiri Olsa return -1; 384edbe9817SJiri Olsa 38554cf776aSSebastian Andrzej Siewior ret = value_set_s32(cw, event, "perf_pid", sample->pid); 386edbe9817SJiri Olsa if (ret) 387edbe9817SJiri Olsa return -1; 388edbe9817SJiri Olsa } 389edbe9817SJiri Olsa 390edbe9817SJiri Olsa if ((type & PERF_SAMPLE_ID) || 391edbe9817SJiri Olsa (type & PERF_SAMPLE_IDENTIFIER)) { 39254cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_id", sample->id); 393edbe9817SJiri Olsa if (ret) 394edbe9817SJiri Olsa return -1; 395edbe9817SJiri Olsa } 396edbe9817SJiri Olsa 397edbe9817SJiri Olsa if (type & PERF_SAMPLE_STREAM_ID) { 39854cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_stream_id", sample->stream_id); 399edbe9817SJiri Olsa if (ret) 400edbe9817SJiri Olsa return -1; 401edbe9817SJiri Olsa } 402edbe9817SJiri Olsa 403edbe9817SJiri Olsa if (type & PERF_SAMPLE_PERIOD) { 40454cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_period", sample->period); 405edbe9817SJiri Olsa if (ret) 406edbe9817SJiri Olsa return -1; 407edbe9817SJiri Olsa } 408edbe9817SJiri Olsa 409edbe9817SJiri Olsa if (type & PERF_SAMPLE_WEIGHT) { 41054cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_weight", sample->weight); 411edbe9817SJiri Olsa if (ret) 412edbe9817SJiri Olsa return -1; 413edbe9817SJiri Olsa } 414edbe9817SJiri Olsa 415edbe9817SJiri Olsa if (type & PERF_SAMPLE_DATA_SRC) { 41654cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_data_src", 41754cf776aSSebastian Andrzej Siewior sample->data_src); 418edbe9817SJiri Olsa if (ret) 419edbe9817SJiri Olsa return -1; 420edbe9817SJiri Olsa } 421edbe9817SJiri Olsa 422edbe9817SJiri Olsa if (type & PERF_SAMPLE_TRANSACTION) { 42354cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_transaction", 42454cf776aSSebastian Andrzej Siewior sample->transaction); 425edbe9817SJiri Olsa if (ret) 426edbe9817SJiri Olsa return -1; 427edbe9817SJiri Olsa } 428edbe9817SJiri Olsa 429edbe9817SJiri Olsa return 0; 430edbe9817SJiri Olsa } 431edbe9817SJiri Olsa 43290e129ffSSebastian Andrzej Siewior static int ctf_stream__flush(struct ctf_stream *cs) 43390e129ffSSebastian Andrzej Siewior { 43490e129ffSSebastian Andrzej Siewior int err = 0; 43590e129ffSSebastian Andrzej Siewior 43690e129ffSSebastian Andrzej Siewior if (cs) { 43790e129ffSSebastian Andrzej Siewior err = bt_ctf_stream_flush(cs->stream); 43890e129ffSSebastian Andrzej Siewior if (err) 43990e129ffSSebastian Andrzej Siewior pr_err("CTF stream %d flush failed\n", cs->cpu); 44090e129ffSSebastian Andrzej Siewior 44189e5fa88SJiri Olsa pr("Flush stream for cpu %d (%u samples)\n", 44289e5fa88SJiri Olsa cs->cpu, cs->count); 44389e5fa88SJiri Olsa 44489e5fa88SJiri Olsa cs->count = 0; 44590e129ffSSebastian Andrzej Siewior } 44690e129ffSSebastian Andrzej Siewior 44790e129ffSSebastian Andrzej Siewior return err; 44890e129ffSSebastian Andrzej Siewior } 44990e129ffSSebastian Andrzej Siewior 45090e129ffSSebastian Andrzej Siewior static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu) 45190e129ffSSebastian Andrzej Siewior { 45290e129ffSSebastian Andrzej Siewior struct ctf_stream *cs; 45390e129ffSSebastian Andrzej Siewior struct bt_ctf_field *pkt_ctx = NULL; 45490e129ffSSebastian Andrzej Siewior struct bt_ctf_field *cpu_field = NULL; 45590e129ffSSebastian Andrzej Siewior struct bt_ctf_stream *stream = NULL; 45690e129ffSSebastian Andrzej Siewior int ret; 45790e129ffSSebastian Andrzej Siewior 45890e129ffSSebastian Andrzej Siewior cs = zalloc(sizeof(*cs)); 45990e129ffSSebastian Andrzej Siewior if (!cs) { 46090e129ffSSebastian Andrzej Siewior pr_err("Failed to allocate ctf stream\n"); 46190e129ffSSebastian Andrzej Siewior return NULL; 46290e129ffSSebastian Andrzej Siewior } 46390e129ffSSebastian Andrzej Siewior 46490e129ffSSebastian Andrzej Siewior stream = bt_ctf_writer_create_stream(cw->writer, cw->stream_class); 46590e129ffSSebastian Andrzej Siewior if (!stream) { 46690e129ffSSebastian Andrzej Siewior pr_err("Failed to create CTF stream\n"); 46790e129ffSSebastian Andrzej Siewior goto out; 46890e129ffSSebastian Andrzej Siewior } 46990e129ffSSebastian Andrzej Siewior 47090e129ffSSebastian Andrzej Siewior pkt_ctx = bt_ctf_stream_get_packet_context(stream); 47190e129ffSSebastian Andrzej Siewior if (!pkt_ctx) { 47290e129ffSSebastian Andrzej Siewior pr_err("Failed to obtain packet context\n"); 47390e129ffSSebastian Andrzej Siewior goto out; 47490e129ffSSebastian Andrzej Siewior } 47590e129ffSSebastian Andrzej Siewior 47690e129ffSSebastian Andrzej Siewior cpu_field = bt_ctf_field_structure_get_field(pkt_ctx, "cpu_id"); 47790e129ffSSebastian Andrzej Siewior bt_ctf_field_put(pkt_ctx); 47890e129ffSSebastian Andrzej Siewior if (!cpu_field) { 47990e129ffSSebastian Andrzej Siewior pr_err("Failed to obtain cpu field\n"); 48090e129ffSSebastian Andrzej Siewior goto out; 48190e129ffSSebastian Andrzej Siewior } 48290e129ffSSebastian Andrzej Siewior 48390e129ffSSebastian Andrzej Siewior ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu); 48490e129ffSSebastian Andrzej Siewior if (ret) { 48590e129ffSSebastian Andrzej Siewior pr_err("Failed to update CPU number\n"); 48690e129ffSSebastian Andrzej Siewior goto out; 48790e129ffSSebastian Andrzej Siewior } 48890e129ffSSebastian Andrzej Siewior 48990e129ffSSebastian Andrzej Siewior bt_ctf_field_put(cpu_field); 49090e129ffSSebastian Andrzej Siewior 49190e129ffSSebastian Andrzej Siewior cs->cpu = cpu; 49290e129ffSSebastian Andrzej Siewior cs->stream = stream; 49390e129ffSSebastian Andrzej Siewior return cs; 49490e129ffSSebastian Andrzej Siewior 49590e129ffSSebastian Andrzej Siewior out: 49690e129ffSSebastian Andrzej Siewior if (cpu_field) 49790e129ffSSebastian Andrzej Siewior bt_ctf_field_put(cpu_field); 49890e129ffSSebastian Andrzej Siewior if (stream) 49990e129ffSSebastian Andrzej Siewior bt_ctf_stream_put(stream); 50090e129ffSSebastian Andrzej Siewior 50190e129ffSSebastian Andrzej Siewior free(cs); 50290e129ffSSebastian Andrzej Siewior return NULL; 50390e129ffSSebastian Andrzej Siewior } 50490e129ffSSebastian Andrzej Siewior 50590e129ffSSebastian Andrzej Siewior static void ctf_stream__delete(struct ctf_stream *cs) 50690e129ffSSebastian Andrzej Siewior { 50790e129ffSSebastian Andrzej Siewior if (cs) { 50890e129ffSSebastian Andrzej Siewior bt_ctf_stream_put(cs->stream); 50990e129ffSSebastian Andrzej Siewior free(cs); 51090e129ffSSebastian Andrzej Siewior } 51190e129ffSSebastian Andrzej Siewior } 51290e129ffSSebastian Andrzej Siewior 51390e129ffSSebastian Andrzej Siewior static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu) 51490e129ffSSebastian Andrzej Siewior { 51590e129ffSSebastian Andrzej Siewior struct ctf_stream *cs = cw->stream[cpu]; 51690e129ffSSebastian Andrzej Siewior 51790e129ffSSebastian Andrzej Siewior if (!cs) { 51890e129ffSSebastian Andrzej Siewior cs = ctf_stream__create(cw, cpu); 51990e129ffSSebastian Andrzej Siewior cw->stream[cpu] = cs; 52090e129ffSSebastian Andrzej Siewior } 52190e129ffSSebastian Andrzej Siewior 52290e129ffSSebastian Andrzej Siewior return cs; 52390e129ffSSebastian Andrzej Siewior } 52490e129ffSSebastian Andrzej Siewior 52590e129ffSSebastian Andrzej Siewior static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample, 52690e129ffSSebastian Andrzej Siewior struct perf_evsel *evsel) 52790e129ffSSebastian Andrzej Siewior { 52890e129ffSSebastian Andrzej Siewior int cpu = 0; 52990e129ffSSebastian Andrzej Siewior 53090e129ffSSebastian Andrzej Siewior if (evsel->attr.sample_type & PERF_SAMPLE_CPU) 53190e129ffSSebastian Andrzej Siewior cpu = sample->cpu; 53290e129ffSSebastian Andrzej Siewior 53390e129ffSSebastian Andrzej Siewior if (cpu > cw->stream_cnt) { 53490e129ffSSebastian Andrzej Siewior pr_err("Event was recorded for CPU %d, limit is at %d.\n", 53590e129ffSSebastian Andrzej Siewior cpu, cw->stream_cnt); 53690e129ffSSebastian Andrzej Siewior cpu = 0; 53790e129ffSSebastian Andrzej Siewior } 53890e129ffSSebastian Andrzej Siewior 53990e129ffSSebastian Andrzej Siewior return cpu; 54090e129ffSSebastian Andrzej Siewior } 54190e129ffSSebastian Andrzej Siewior 54289e5fa88SJiri Olsa #define STREAM_FLUSH_COUNT 100000 54389e5fa88SJiri Olsa 54489e5fa88SJiri Olsa /* 54589e5fa88SJiri Olsa * Currently we have no other way to determine the 54689e5fa88SJiri Olsa * time for the stream flush other than keep track 54789e5fa88SJiri Olsa * of the number of events and check it against 54889e5fa88SJiri Olsa * threshold. 54989e5fa88SJiri Olsa */ 55089e5fa88SJiri Olsa static bool is_flush_needed(struct ctf_stream *cs) 55189e5fa88SJiri Olsa { 55289e5fa88SJiri Olsa return cs->count >= STREAM_FLUSH_COUNT; 55389e5fa88SJiri Olsa } 55489e5fa88SJiri Olsa 555edbe9817SJiri Olsa static int process_sample_event(struct perf_tool *tool, 556edbe9817SJiri Olsa union perf_event *_event __maybe_unused, 557edbe9817SJiri Olsa struct perf_sample *sample, 558edbe9817SJiri Olsa struct perf_evsel *evsel, 559edbe9817SJiri Olsa struct machine *machine __maybe_unused) 560edbe9817SJiri Olsa { 561edbe9817SJiri Olsa struct convert *c = container_of(tool, struct convert, tool); 562edbe9817SJiri Olsa struct evsel_priv *priv = evsel->priv; 563edbe9817SJiri Olsa struct ctf_writer *cw = &c->writer; 56490e129ffSSebastian Andrzej Siewior struct ctf_stream *cs; 565edbe9817SJiri Olsa struct bt_ctf_event_class *event_class; 566edbe9817SJiri Olsa struct bt_ctf_event *event; 567edbe9817SJiri Olsa int ret; 568edbe9817SJiri Olsa 569edbe9817SJiri Olsa if (WARN_ONCE(!priv, "Failed to setup all events.\n")) 570edbe9817SJiri Olsa return 0; 571edbe9817SJiri Olsa 572edbe9817SJiri Olsa event_class = priv->event_class; 573edbe9817SJiri Olsa 574edbe9817SJiri Olsa /* update stats */ 575edbe9817SJiri Olsa c->events_count++; 576edbe9817SJiri Olsa c->events_size += _event->header.size; 577edbe9817SJiri Olsa 578edbe9817SJiri Olsa pr_time2(sample->time, "sample %" PRIu64 "\n", c->events_count); 579edbe9817SJiri Olsa 580edbe9817SJiri Olsa event = bt_ctf_event_create(event_class); 581edbe9817SJiri Olsa if (!event) { 582edbe9817SJiri Olsa pr_err("Failed to create an CTF event\n"); 583edbe9817SJiri Olsa return -1; 584edbe9817SJiri Olsa } 585edbe9817SJiri Olsa 586edbe9817SJiri Olsa bt_ctf_clock_set_time(cw->clock, sample->time); 587edbe9817SJiri Olsa 588edbe9817SJiri Olsa ret = add_generic_values(cw, event, evsel, sample); 589edbe9817SJiri Olsa if (ret) 590edbe9817SJiri Olsa return -1; 591edbe9817SJiri Olsa 59269364727SSebastian Andrzej Siewior if (evsel->attr.type == PERF_TYPE_TRACEPOINT) { 59369364727SSebastian Andrzej Siewior ret = add_tracepoint_values(cw, event_class, event, 59469364727SSebastian Andrzej Siewior evsel, sample); 59569364727SSebastian Andrzej Siewior if (ret) 59669364727SSebastian Andrzej Siewior return -1; 59769364727SSebastian Andrzej Siewior } 59869364727SSebastian Andrzej Siewior 59990e129ffSSebastian Andrzej Siewior cs = ctf_stream(cw, get_sample_cpu(cw, sample, evsel)); 60089e5fa88SJiri Olsa if (cs) { 60189e5fa88SJiri Olsa if (is_flush_needed(cs)) 60289e5fa88SJiri Olsa ctf_stream__flush(cs); 60389e5fa88SJiri Olsa 60489e5fa88SJiri Olsa cs->count++; 60590e129ffSSebastian Andrzej Siewior bt_ctf_stream_append_event(cs->stream, event); 60689e5fa88SJiri Olsa } 60790e129ffSSebastian Andrzej Siewior 608edbe9817SJiri Olsa bt_ctf_event_put(event); 60990e129ffSSebastian Andrzej Siewior return cs ? 0 : -1; 610edbe9817SJiri Olsa } 611edbe9817SJiri Olsa 612e0a7cce5SWang Nan /* If dup < 0, add a prefix. Else, add _dupl_X suffix. */ 613e0a7cce5SWang Nan static char *change_name(char *name, char *orig_name, int dup) 614e0a7cce5SWang Nan { 615e0a7cce5SWang Nan char *new_name = NULL; 616e0a7cce5SWang Nan size_t len; 617e0a7cce5SWang Nan 618e0a7cce5SWang Nan if (!name) 619e0a7cce5SWang Nan name = orig_name; 620e0a7cce5SWang Nan 621e0a7cce5SWang Nan if (dup >= 10) 622e0a7cce5SWang Nan goto out; 623e0a7cce5SWang Nan /* 624e0a7cce5SWang Nan * Add '_' prefix to potential keywork. According to 625e0a7cce5SWang Nan * Mathieu Desnoyers (https://lkml.org/lkml/2015/1/23/652), 626e0a7cce5SWang Nan * futher CTF spec updating may require us to use '$'. 627e0a7cce5SWang Nan */ 628e0a7cce5SWang Nan if (dup < 0) 629e0a7cce5SWang Nan len = strlen(name) + sizeof("_"); 630e0a7cce5SWang Nan else 631e0a7cce5SWang Nan len = strlen(orig_name) + sizeof("_dupl_X"); 632e0a7cce5SWang Nan 633e0a7cce5SWang Nan new_name = malloc(len); 634e0a7cce5SWang Nan if (!new_name) 635e0a7cce5SWang Nan goto out; 636e0a7cce5SWang Nan 637e0a7cce5SWang Nan if (dup < 0) 638e0a7cce5SWang Nan snprintf(new_name, len, "_%s", name); 639e0a7cce5SWang Nan else 640e0a7cce5SWang Nan snprintf(new_name, len, "%s_dupl_%d", orig_name, dup); 641e0a7cce5SWang Nan 642e0a7cce5SWang Nan out: 643e0a7cce5SWang Nan if (name != orig_name) 644e0a7cce5SWang Nan free(name); 645e0a7cce5SWang Nan return new_name; 646e0a7cce5SWang Nan } 647e0a7cce5SWang Nan 648e0a7cce5SWang Nan static int event_class_add_field(struct bt_ctf_event_class *event_class, 649e0a7cce5SWang Nan struct bt_ctf_field_type *type, 650e0a7cce5SWang Nan struct format_field *field) 651e0a7cce5SWang Nan { 652e0a7cce5SWang Nan struct bt_ctf_field_type *t = NULL; 653e0a7cce5SWang Nan char *name; 654e0a7cce5SWang Nan int dup = 1; 655e0a7cce5SWang Nan int ret; 656e0a7cce5SWang Nan 657e0a7cce5SWang Nan /* alias was already assigned */ 658e0a7cce5SWang Nan if (field->alias != field->name) 659e0a7cce5SWang Nan return bt_ctf_event_class_add_field(event_class, type, 660e0a7cce5SWang Nan (char *)field->alias); 661e0a7cce5SWang Nan 662e0a7cce5SWang Nan name = field->name; 663e0a7cce5SWang Nan 664e0a7cce5SWang Nan /* If 'name' is a keywork, add prefix. */ 665e0a7cce5SWang Nan if (bt_ctf_validate_identifier(name)) 666e0a7cce5SWang Nan name = change_name(name, field->name, -1); 667e0a7cce5SWang Nan 668e0a7cce5SWang Nan if (!name) { 669e0a7cce5SWang Nan pr_err("Failed to fix invalid identifier."); 670e0a7cce5SWang Nan return -1; 671e0a7cce5SWang Nan } 672e0a7cce5SWang Nan while ((t = bt_ctf_event_class_get_field_by_name(event_class, name))) { 673e0a7cce5SWang Nan bt_ctf_field_type_put(t); 674e0a7cce5SWang Nan name = change_name(name, field->name, dup++); 675e0a7cce5SWang Nan if (!name) { 676e0a7cce5SWang Nan pr_err("Failed to create dup name for '%s'\n", field->name); 677e0a7cce5SWang Nan return -1; 678e0a7cce5SWang Nan } 679e0a7cce5SWang Nan } 680e0a7cce5SWang Nan 681e0a7cce5SWang Nan ret = bt_ctf_event_class_add_field(event_class, type, name); 682e0a7cce5SWang Nan if (!ret) 683e0a7cce5SWang Nan field->alias = name; 684e0a7cce5SWang Nan 685e0a7cce5SWang Nan return ret; 686e0a7cce5SWang Nan } 687e0a7cce5SWang Nan 68869364727SSebastian Andrzej Siewior static int add_tracepoint_fields_types(struct ctf_writer *cw, 68969364727SSebastian Andrzej Siewior struct format_field *fields, 69069364727SSebastian Andrzej Siewior struct bt_ctf_event_class *event_class) 69169364727SSebastian Andrzej Siewior { 69269364727SSebastian Andrzej Siewior struct format_field *field; 69369364727SSebastian Andrzej Siewior int ret; 69469364727SSebastian Andrzej Siewior 69569364727SSebastian Andrzej Siewior for (field = fields; field; field = field->next) { 69669364727SSebastian Andrzej Siewior struct bt_ctf_field_type *type; 69769364727SSebastian Andrzej Siewior unsigned long flags = field->flags; 69869364727SSebastian Andrzej Siewior 69969364727SSebastian Andrzej Siewior pr2(" field '%s'\n", field->name); 70069364727SSebastian Andrzej Siewior 70169364727SSebastian Andrzej Siewior type = get_tracepoint_field_type(cw, field); 70269364727SSebastian Andrzej Siewior if (!type) 70369364727SSebastian Andrzej Siewior return -1; 70469364727SSebastian Andrzej Siewior 70569364727SSebastian Andrzej Siewior /* 70669364727SSebastian Andrzej Siewior * A string is an array of chars. For this we use the string 70769364727SSebastian Andrzej Siewior * type and don't care that it is an array. What we don't 70869364727SSebastian Andrzej Siewior * support is an array of strings. 70969364727SSebastian Andrzej Siewior */ 71069364727SSebastian Andrzej Siewior if (flags & FIELD_IS_STRING) 71169364727SSebastian Andrzej Siewior flags &= ~FIELD_IS_ARRAY; 71269364727SSebastian Andrzej Siewior 71369364727SSebastian Andrzej Siewior if (flags & FIELD_IS_ARRAY) 71469364727SSebastian Andrzej Siewior type = bt_ctf_field_type_array_create(type, field->arraylen); 71569364727SSebastian Andrzej Siewior 716e0a7cce5SWang Nan ret = event_class_add_field(event_class, type, field); 71769364727SSebastian Andrzej Siewior 71869364727SSebastian Andrzej Siewior if (flags & FIELD_IS_ARRAY) 71969364727SSebastian Andrzej Siewior bt_ctf_field_type_put(type); 72069364727SSebastian Andrzej Siewior 72169364727SSebastian Andrzej Siewior if (ret) { 722e0a7cce5SWang Nan pr_err("Failed to add field '%s': %d\n", 723e0a7cce5SWang Nan field->name, ret); 72469364727SSebastian Andrzej Siewior return -1; 72569364727SSebastian Andrzej Siewior } 72669364727SSebastian Andrzej Siewior } 72769364727SSebastian Andrzej Siewior 72869364727SSebastian Andrzej Siewior return 0; 72969364727SSebastian Andrzej Siewior } 73069364727SSebastian Andrzej Siewior 73169364727SSebastian Andrzej Siewior static int add_tracepoint_types(struct ctf_writer *cw, 73269364727SSebastian Andrzej Siewior struct perf_evsel *evsel, 73369364727SSebastian Andrzej Siewior struct bt_ctf_event_class *class) 73469364727SSebastian Andrzej Siewior { 73569364727SSebastian Andrzej Siewior struct format_field *common_fields = evsel->tp_format->format.common_fields; 73669364727SSebastian Andrzej Siewior struct format_field *fields = evsel->tp_format->format.fields; 73769364727SSebastian Andrzej Siewior int ret; 73869364727SSebastian Andrzej Siewior 73969364727SSebastian Andrzej Siewior ret = add_tracepoint_fields_types(cw, common_fields, class); 74069364727SSebastian Andrzej Siewior if (!ret) 74169364727SSebastian Andrzej Siewior ret = add_tracepoint_fields_types(cw, fields, class); 74269364727SSebastian Andrzej Siewior 74369364727SSebastian Andrzej Siewior return ret; 74469364727SSebastian Andrzej Siewior } 74569364727SSebastian Andrzej Siewior 746edbe9817SJiri Olsa static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel, 747edbe9817SJiri Olsa struct bt_ctf_event_class *event_class) 748edbe9817SJiri Olsa { 749edbe9817SJiri Olsa u64 type = evsel->attr.sample_type; 750edbe9817SJiri Olsa 751edbe9817SJiri Olsa /* 752edbe9817SJiri Olsa * missing: 753edbe9817SJiri Olsa * PERF_SAMPLE_TIME - not needed as we have it in 754edbe9817SJiri Olsa * ctf event header 755edbe9817SJiri Olsa * PERF_SAMPLE_READ - TODO 756edbe9817SJiri Olsa * PERF_SAMPLE_CALLCHAIN - TODO 757edbe9817SJiri Olsa * PERF_SAMPLE_RAW - tracepoint fields are handled separately 758edbe9817SJiri Olsa * PERF_SAMPLE_BRANCH_STACK - TODO 759edbe9817SJiri Olsa * PERF_SAMPLE_REGS_USER - TODO 760edbe9817SJiri Olsa * PERF_SAMPLE_STACK_USER - TODO 761edbe9817SJiri Olsa */ 762edbe9817SJiri Olsa 763edbe9817SJiri Olsa #define ADD_FIELD(cl, t, n) \ 764edbe9817SJiri Olsa do { \ 765edbe9817SJiri Olsa pr2(" field '%s'\n", n); \ 766edbe9817SJiri Olsa if (bt_ctf_event_class_add_field(cl, t, n)) { \ 767e0a7cce5SWang Nan pr_err("Failed to add field '%s';\n", n); \ 768edbe9817SJiri Olsa return -1; \ 769edbe9817SJiri Olsa } \ 770edbe9817SJiri Olsa } while (0) 771edbe9817SJiri Olsa 772edbe9817SJiri Olsa if (type & PERF_SAMPLE_IP) 77354cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64_hex, "perf_ip"); 774edbe9817SJiri Olsa 775edbe9817SJiri Olsa if (type & PERF_SAMPLE_TID) { 77654cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.s32, "perf_tid"); 77754cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.s32, "perf_pid"); 778edbe9817SJiri Olsa } 779edbe9817SJiri Olsa 780edbe9817SJiri Olsa if ((type & PERF_SAMPLE_ID) || 781edbe9817SJiri Olsa (type & PERF_SAMPLE_IDENTIFIER)) 78254cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_id"); 783edbe9817SJiri Olsa 784edbe9817SJiri Olsa if (type & PERF_SAMPLE_STREAM_ID) 78554cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_stream_id"); 786edbe9817SJiri Olsa 787edbe9817SJiri Olsa if (type & PERF_SAMPLE_PERIOD) 78854cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_period"); 789edbe9817SJiri Olsa 790edbe9817SJiri Olsa if (type & PERF_SAMPLE_WEIGHT) 79154cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_weight"); 792edbe9817SJiri Olsa 793edbe9817SJiri Olsa if (type & PERF_SAMPLE_DATA_SRC) 79454cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_data_src"); 795edbe9817SJiri Olsa 796edbe9817SJiri Olsa if (type & PERF_SAMPLE_TRANSACTION) 79754cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_transaction"); 798edbe9817SJiri Olsa 799edbe9817SJiri Olsa #undef ADD_FIELD 800edbe9817SJiri Olsa return 0; 801edbe9817SJiri Olsa } 802edbe9817SJiri Olsa 803edbe9817SJiri Olsa static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel) 804edbe9817SJiri Olsa { 805edbe9817SJiri Olsa struct bt_ctf_event_class *event_class; 806edbe9817SJiri Olsa struct evsel_priv *priv; 807edbe9817SJiri Olsa const char *name = perf_evsel__name(evsel); 808edbe9817SJiri Olsa int ret; 809edbe9817SJiri Olsa 810edbe9817SJiri Olsa pr("Adding event '%s' (type %d)\n", name, evsel->attr.type); 811edbe9817SJiri Olsa 812edbe9817SJiri Olsa event_class = bt_ctf_event_class_create(name); 813edbe9817SJiri Olsa if (!event_class) 814edbe9817SJiri Olsa return -1; 815edbe9817SJiri Olsa 816edbe9817SJiri Olsa ret = add_generic_types(cw, evsel, event_class); 817edbe9817SJiri Olsa if (ret) 818edbe9817SJiri Olsa goto err; 819edbe9817SJiri Olsa 82069364727SSebastian Andrzej Siewior if (evsel->attr.type == PERF_TYPE_TRACEPOINT) { 82169364727SSebastian Andrzej Siewior ret = add_tracepoint_types(cw, evsel, event_class); 82269364727SSebastian Andrzej Siewior if (ret) 82369364727SSebastian Andrzej Siewior goto err; 82469364727SSebastian Andrzej Siewior } 82569364727SSebastian Andrzej Siewior 826edbe9817SJiri Olsa ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class); 827edbe9817SJiri Olsa if (ret) { 828edbe9817SJiri Olsa pr("Failed to add event class into stream.\n"); 829edbe9817SJiri Olsa goto err; 830edbe9817SJiri Olsa } 831edbe9817SJiri Olsa 832edbe9817SJiri Olsa priv = malloc(sizeof(*priv)); 833edbe9817SJiri Olsa if (!priv) 834edbe9817SJiri Olsa goto err; 835edbe9817SJiri Olsa 836edbe9817SJiri Olsa priv->event_class = event_class; 837edbe9817SJiri Olsa evsel->priv = priv; 838edbe9817SJiri Olsa return 0; 839edbe9817SJiri Olsa 840edbe9817SJiri Olsa err: 841edbe9817SJiri Olsa bt_ctf_event_class_put(event_class); 842edbe9817SJiri Olsa pr_err("Failed to add event '%s'.\n", name); 843edbe9817SJiri Olsa return -1; 844edbe9817SJiri Olsa } 845edbe9817SJiri Olsa 846edbe9817SJiri Olsa static int setup_events(struct ctf_writer *cw, struct perf_session *session) 847edbe9817SJiri Olsa { 848edbe9817SJiri Olsa struct perf_evlist *evlist = session->evlist; 849edbe9817SJiri Olsa struct perf_evsel *evsel; 850edbe9817SJiri Olsa int ret; 851edbe9817SJiri Olsa 852edbe9817SJiri Olsa evlist__for_each(evlist, evsel) { 853edbe9817SJiri Olsa ret = add_event(cw, evsel); 854edbe9817SJiri Olsa if (ret) 855edbe9817SJiri Olsa return ret; 856edbe9817SJiri Olsa } 857edbe9817SJiri Olsa return 0; 858edbe9817SJiri Olsa } 859edbe9817SJiri Olsa 86090e129ffSSebastian Andrzej Siewior static int setup_streams(struct ctf_writer *cw, struct perf_session *session) 86190e129ffSSebastian Andrzej Siewior { 86290e129ffSSebastian Andrzej Siewior struct ctf_stream **stream; 86390e129ffSSebastian Andrzej Siewior struct perf_header *ph = &session->header; 86490e129ffSSebastian Andrzej Siewior int ncpus; 86590e129ffSSebastian Andrzej Siewior 86690e129ffSSebastian Andrzej Siewior /* 86790e129ffSSebastian Andrzej Siewior * Try to get the number of cpus used in the data file, 86890e129ffSSebastian Andrzej Siewior * if not present fallback to the MAX_CPUS. 86990e129ffSSebastian Andrzej Siewior */ 87090e129ffSSebastian Andrzej Siewior ncpus = ph->env.nr_cpus_avail ?: MAX_CPUS; 87190e129ffSSebastian Andrzej Siewior 87290e129ffSSebastian Andrzej Siewior stream = zalloc(sizeof(*stream) * ncpus); 87390e129ffSSebastian Andrzej Siewior if (!stream) { 87490e129ffSSebastian Andrzej Siewior pr_err("Failed to allocate streams.\n"); 87590e129ffSSebastian Andrzej Siewior return -ENOMEM; 87690e129ffSSebastian Andrzej Siewior } 87790e129ffSSebastian Andrzej Siewior 87890e129ffSSebastian Andrzej Siewior cw->stream = stream; 87990e129ffSSebastian Andrzej Siewior cw->stream_cnt = ncpus; 88090e129ffSSebastian Andrzej Siewior return 0; 88190e129ffSSebastian Andrzej Siewior } 88290e129ffSSebastian Andrzej Siewior 88390e129ffSSebastian Andrzej Siewior static void free_streams(struct ctf_writer *cw) 88490e129ffSSebastian Andrzej Siewior { 88590e129ffSSebastian Andrzej Siewior int cpu; 88690e129ffSSebastian Andrzej Siewior 88790e129ffSSebastian Andrzej Siewior for (cpu = 0; cpu < cw->stream_cnt; cpu++) 88890e129ffSSebastian Andrzej Siewior ctf_stream__delete(cw->stream[cpu]); 88990e129ffSSebastian Andrzej Siewior 89090e129ffSSebastian Andrzej Siewior free(cw->stream); 89190e129ffSSebastian Andrzej Siewior } 89290e129ffSSebastian Andrzej Siewior 893edbe9817SJiri Olsa static int ctf_writer__setup_env(struct ctf_writer *cw, 894edbe9817SJiri Olsa struct perf_session *session) 895edbe9817SJiri Olsa { 896edbe9817SJiri Olsa struct perf_header *header = &session->header; 897edbe9817SJiri Olsa struct bt_ctf_writer *writer = cw->writer; 898edbe9817SJiri Olsa 899edbe9817SJiri Olsa #define ADD(__n, __v) \ 900edbe9817SJiri Olsa do { \ 901edbe9817SJiri Olsa if (bt_ctf_writer_add_environment_field(writer, __n, __v)) \ 902edbe9817SJiri Olsa return -1; \ 903edbe9817SJiri Olsa } while (0) 904edbe9817SJiri Olsa 905edbe9817SJiri Olsa ADD("host", header->env.hostname); 906edbe9817SJiri Olsa ADD("sysname", "Linux"); 907edbe9817SJiri Olsa ADD("release", header->env.os_release); 908edbe9817SJiri Olsa ADD("version", header->env.version); 909edbe9817SJiri Olsa ADD("machine", header->env.arch); 910edbe9817SJiri Olsa ADD("domain", "kernel"); 911edbe9817SJiri Olsa ADD("tracer_name", "perf"); 912edbe9817SJiri Olsa 913edbe9817SJiri Olsa #undef ADD 914edbe9817SJiri Olsa return 0; 915edbe9817SJiri Olsa } 916edbe9817SJiri Olsa 917edbe9817SJiri Olsa static int ctf_writer__setup_clock(struct ctf_writer *cw) 918edbe9817SJiri Olsa { 919edbe9817SJiri Olsa struct bt_ctf_clock *clock = cw->clock; 920edbe9817SJiri Olsa 921edbe9817SJiri Olsa bt_ctf_clock_set_description(clock, "perf clock"); 922edbe9817SJiri Olsa 923edbe9817SJiri Olsa #define SET(__n, __v) \ 924edbe9817SJiri Olsa do { \ 925edbe9817SJiri Olsa if (bt_ctf_clock_set_##__n(clock, __v)) \ 926edbe9817SJiri Olsa return -1; \ 927edbe9817SJiri Olsa } while (0) 928edbe9817SJiri Olsa 929edbe9817SJiri Olsa SET(frequency, 1000000000); 930edbe9817SJiri Olsa SET(offset_s, 0); 931edbe9817SJiri Olsa SET(offset, 0); 932edbe9817SJiri Olsa SET(precision, 10); 933edbe9817SJiri Olsa SET(is_absolute, 0); 934edbe9817SJiri Olsa 935edbe9817SJiri Olsa #undef SET 936edbe9817SJiri Olsa return 0; 937edbe9817SJiri Olsa } 938edbe9817SJiri Olsa 939edbe9817SJiri Olsa static struct bt_ctf_field_type *create_int_type(int size, bool sign, bool hex) 940edbe9817SJiri Olsa { 941edbe9817SJiri Olsa struct bt_ctf_field_type *type; 942edbe9817SJiri Olsa 943edbe9817SJiri Olsa type = bt_ctf_field_type_integer_create(size); 944edbe9817SJiri Olsa if (!type) 945edbe9817SJiri Olsa return NULL; 946edbe9817SJiri Olsa 947edbe9817SJiri Olsa if (sign && 948edbe9817SJiri Olsa bt_ctf_field_type_integer_set_signed(type, 1)) 949edbe9817SJiri Olsa goto err; 950edbe9817SJiri Olsa 951edbe9817SJiri Olsa if (hex && 952edbe9817SJiri Olsa bt_ctf_field_type_integer_set_base(type, BT_CTF_INTEGER_BASE_HEXADECIMAL)) 953edbe9817SJiri Olsa goto err; 954edbe9817SJiri Olsa 955edbe9817SJiri Olsa pr2("Created type: INTEGER %d-bit %ssigned %s\n", 956edbe9817SJiri Olsa size, sign ? "un" : "", hex ? "hex" : ""); 957edbe9817SJiri Olsa return type; 958edbe9817SJiri Olsa 959edbe9817SJiri Olsa err: 960edbe9817SJiri Olsa bt_ctf_field_type_put(type); 961edbe9817SJiri Olsa return NULL; 962edbe9817SJiri Olsa } 963edbe9817SJiri Olsa 964edbe9817SJiri Olsa static void ctf_writer__cleanup_data(struct ctf_writer *cw) 965edbe9817SJiri Olsa { 966edbe9817SJiri Olsa unsigned int i; 967edbe9817SJiri Olsa 968edbe9817SJiri Olsa for (i = 0; i < ARRAY_SIZE(cw->data.array); i++) 969edbe9817SJiri Olsa bt_ctf_field_type_put(cw->data.array[i]); 970edbe9817SJiri Olsa } 971edbe9817SJiri Olsa 972edbe9817SJiri Olsa static int ctf_writer__init_data(struct ctf_writer *cw) 973edbe9817SJiri Olsa { 974edbe9817SJiri Olsa #define CREATE_INT_TYPE(type, size, sign, hex) \ 975edbe9817SJiri Olsa do { \ 976edbe9817SJiri Olsa (type) = create_int_type(size, sign, hex); \ 977edbe9817SJiri Olsa if (!(type)) \ 978edbe9817SJiri Olsa goto err; \ 979edbe9817SJiri Olsa } while (0) 980edbe9817SJiri Olsa 981edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.s64, 64, true, false); 982edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.u64, 64, false, false); 983edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.s32, 32, true, false); 984edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.u32, 32, false, false); 985edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true); 986edbe9817SJiri Olsa 987edbe9817SJiri Olsa cw->data.string = bt_ctf_field_type_string_create(); 988edbe9817SJiri Olsa if (cw->data.string) 989edbe9817SJiri Olsa return 0; 990edbe9817SJiri Olsa 991edbe9817SJiri Olsa err: 992edbe9817SJiri Olsa ctf_writer__cleanup_data(cw); 993edbe9817SJiri Olsa pr_err("Failed to create data types.\n"); 994edbe9817SJiri Olsa return -1; 995edbe9817SJiri Olsa } 996edbe9817SJiri Olsa 997edbe9817SJiri Olsa static void ctf_writer__cleanup(struct ctf_writer *cw) 998edbe9817SJiri Olsa { 999edbe9817SJiri Olsa ctf_writer__cleanup_data(cw); 1000edbe9817SJiri Olsa 1001edbe9817SJiri Olsa bt_ctf_clock_put(cw->clock); 100290e129ffSSebastian Andrzej Siewior free_streams(cw); 1003edbe9817SJiri Olsa bt_ctf_stream_class_put(cw->stream_class); 1004edbe9817SJiri Olsa bt_ctf_writer_put(cw->writer); 1005edbe9817SJiri Olsa 1006edbe9817SJiri Olsa /* and NULL all the pointers */ 1007edbe9817SJiri Olsa memset(cw, 0, sizeof(*cw)); 1008edbe9817SJiri Olsa } 1009edbe9817SJiri Olsa 1010edbe9817SJiri Olsa static int ctf_writer__init(struct ctf_writer *cw, const char *path) 1011edbe9817SJiri Olsa { 1012edbe9817SJiri Olsa struct bt_ctf_writer *writer; 1013edbe9817SJiri Olsa struct bt_ctf_stream_class *stream_class; 1014edbe9817SJiri Olsa struct bt_ctf_clock *clock; 101590e129ffSSebastian Andrzej Siewior struct bt_ctf_field_type *pkt_ctx_type; 101690e129ffSSebastian Andrzej Siewior int ret; 1017edbe9817SJiri Olsa 1018edbe9817SJiri Olsa /* CTF writer */ 1019edbe9817SJiri Olsa writer = bt_ctf_writer_create(path); 1020edbe9817SJiri Olsa if (!writer) 1021edbe9817SJiri Olsa goto err; 1022edbe9817SJiri Olsa 1023edbe9817SJiri Olsa cw->writer = writer; 1024edbe9817SJiri Olsa 1025edbe9817SJiri Olsa /* CTF clock */ 1026edbe9817SJiri Olsa clock = bt_ctf_clock_create("perf_clock"); 1027edbe9817SJiri Olsa if (!clock) { 1028edbe9817SJiri Olsa pr("Failed to create CTF clock.\n"); 1029edbe9817SJiri Olsa goto err_cleanup; 1030edbe9817SJiri Olsa } 1031edbe9817SJiri Olsa 1032edbe9817SJiri Olsa cw->clock = clock; 1033edbe9817SJiri Olsa 1034edbe9817SJiri Olsa if (ctf_writer__setup_clock(cw)) { 1035edbe9817SJiri Olsa pr("Failed to setup CTF clock.\n"); 1036edbe9817SJiri Olsa goto err_cleanup; 1037edbe9817SJiri Olsa } 1038edbe9817SJiri Olsa 1039edbe9817SJiri Olsa /* CTF stream class */ 1040edbe9817SJiri Olsa stream_class = bt_ctf_stream_class_create("perf_stream"); 1041edbe9817SJiri Olsa if (!stream_class) { 1042edbe9817SJiri Olsa pr("Failed to create CTF stream class.\n"); 1043edbe9817SJiri Olsa goto err_cleanup; 1044edbe9817SJiri Olsa } 1045edbe9817SJiri Olsa 1046edbe9817SJiri Olsa cw->stream_class = stream_class; 1047edbe9817SJiri Olsa 1048edbe9817SJiri Olsa /* CTF clock stream setup */ 1049edbe9817SJiri Olsa if (bt_ctf_stream_class_set_clock(stream_class, clock)) { 1050edbe9817SJiri Olsa pr("Failed to assign CTF clock to stream class.\n"); 1051edbe9817SJiri Olsa goto err_cleanup; 1052edbe9817SJiri Olsa } 1053edbe9817SJiri Olsa 1054edbe9817SJiri Olsa if (ctf_writer__init_data(cw)) 1055edbe9817SJiri Olsa goto err_cleanup; 1056edbe9817SJiri Olsa 105790e129ffSSebastian Andrzej Siewior /* Add cpu_id for packet context */ 105890e129ffSSebastian Andrzej Siewior pkt_ctx_type = bt_ctf_stream_class_get_packet_context_type(stream_class); 105990e129ffSSebastian Andrzej Siewior if (!pkt_ctx_type) 1060edbe9817SJiri Olsa goto err_cleanup; 1061edbe9817SJiri Olsa 106290e129ffSSebastian Andrzej Siewior ret = bt_ctf_field_type_structure_add_field(pkt_ctx_type, cw->data.u32, "cpu_id"); 106390e129ffSSebastian Andrzej Siewior bt_ctf_field_type_put(pkt_ctx_type); 106490e129ffSSebastian Andrzej Siewior if (ret) 106590e129ffSSebastian Andrzej Siewior goto err_cleanup; 1066edbe9817SJiri Olsa 1067edbe9817SJiri Olsa /* CTF clock writer setup */ 1068edbe9817SJiri Olsa if (bt_ctf_writer_add_clock(writer, clock)) { 1069edbe9817SJiri Olsa pr("Failed to assign CTF clock to writer.\n"); 1070edbe9817SJiri Olsa goto err_cleanup; 1071edbe9817SJiri Olsa } 1072edbe9817SJiri Olsa 1073edbe9817SJiri Olsa return 0; 1074edbe9817SJiri Olsa 1075edbe9817SJiri Olsa err_cleanup: 1076edbe9817SJiri Olsa ctf_writer__cleanup(cw); 1077edbe9817SJiri Olsa err: 1078edbe9817SJiri Olsa pr_err("Failed to setup CTF writer.\n"); 1079edbe9817SJiri Olsa return -1; 1080edbe9817SJiri Olsa } 1081edbe9817SJiri Olsa 108290e129ffSSebastian Andrzej Siewior static int ctf_writer__flush_streams(struct ctf_writer *cw) 108390e129ffSSebastian Andrzej Siewior { 108490e129ffSSebastian Andrzej Siewior int cpu, ret = 0; 108590e129ffSSebastian Andrzej Siewior 108690e129ffSSebastian Andrzej Siewior for (cpu = 0; cpu < cw->stream_cnt && !ret; cpu++) 108790e129ffSSebastian Andrzej Siewior ret = ctf_stream__flush(cw->stream[cpu]); 108890e129ffSSebastian Andrzej Siewior 108990e129ffSSebastian Andrzej Siewior return ret; 109090e129ffSSebastian Andrzej Siewior } 109190e129ffSSebastian Andrzej Siewior 10928fa46753SJiri Olsa static int convert__config(const char *var, const char *value, void *cb) 10938fa46753SJiri Olsa { 10948fa46753SJiri Olsa struct convert *c = cb; 10958fa46753SJiri Olsa 10968fa46753SJiri Olsa if (!strcmp(var, "convert.queue-size")) { 10978fa46753SJiri Olsa c->queue_size = perf_config_u64(var, value); 10988fa46753SJiri Olsa return 0; 10998fa46753SJiri Olsa } 11008fa46753SJiri Olsa 11018fa46753SJiri Olsa return perf_default_config(var, value, cb); 11028fa46753SJiri Olsa } 11038fa46753SJiri Olsa 1104bd05954bSYunlong Song int bt_convert__perf2ctf(const char *input, const char *path, bool force) 1105edbe9817SJiri Olsa { 1106edbe9817SJiri Olsa struct perf_session *session; 1107edbe9817SJiri Olsa struct perf_data_file file = { 1108edbe9817SJiri Olsa .path = input, 1109edbe9817SJiri Olsa .mode = PERF_DATA_MODE_READ, 1110bd05954bSYunlong Song .force = force, 1111edbe9817SJiri Olsa }; 1112edbe9817SJiri Olsa struct convert c = { 1113edbe9817SJiri Olsa .tool = { 1114edbe9817SJiri Olsa .sample = process_sample_event, 1115edbe9817SJiri Olsa .mmap = perf_event__process_mmap, 1116edbe9817SJiri Olsa .mmap2 = perf_event__process_mmap2, 1117edbe9817SJiri Olsa .comm = perf_event__process_comm, 1118edbe9817SJiri Olsa .exit = perf_event__process_exit, 1119edbe9817SJiri Olsa .fork = perf_event__process_fork, 1120edbe9817SJiri Olsa .lost = perf_event__process_lost, 1121edbe9817SJiri Olsa .tracing_data = perf_event__process_tracing_data, 1122edbe9817SJiri Olsa .build_id = perf_event__process_build_id, 1123edbe9817SJiri Olsa .ordered_events = true, 1124edbe9817SJiri Olsa .ordering_requires_timestamps = true, 1125edbe9817SJiri Olsa }, 1126edbe9817SJiri Olsa }; 1127edbe9817SJiri Olsa struct ctf_writer *cw = &c.writer; 1128edbe9817SJiri Olsa int err = -1; 1129edbe9817SJiri Olsa 11308fa46753SJiri Olsa perf_config(convert__config, &c); 11318fa46753SJiri Olsa 1132edbe9817SJiri Olsa /* CTF writer */ 1133edbe9817SJiri Olsa if (ctf_writer__init(cw, path)) 1134edbe9817SJiri Olsa return -1; 1135edbe9817SJiri Olsa 1136edbe9817SJiri Olsa /* perf.data session */ 1137b7b61cbeSArnaldo Carvalho de Melo session = perf_session__new(&file, 0, &c.tool); 1138edbe9817SJiri Olsa if (!session) 1139edbe9817SJiri Olsa goto free_writer; 1140edbe9817SJiri Olsa 11418fa46753SJiri Olsa if (c.queue_size) { 11428fa46753SJiri Olsa ordered_events__set_alloc_size(&session->ordered_events, 11438fa46753SJiri Olsa c.queue_size); 11448fa46753SJiri Olsa } 11458fa46753SJiri Olsa 1146edbe9817SJiri Olsa /* CTF writer env/clock setup */ 1147edbe9817SJiri Olsa if (ctf_writer__setup_env(cw, session)) 1148edbe9817SJiri Olsa goto free_session; 1149edbe9817SJiri Olsa 1150edbe9817SJiri Olsa /* CTF events setup */ 1151edbe9817SJiri Olsa if (setup_events(cw, session)) 1152edbe9817SJiri Olsa goto free_session; 1153edbe9817SJiri Olsa 115490e129ffSSebastian Andrzej Siewior if (setup_streams(cw, session)) 115590e129ffSSebastian Andrzej Siewior goto free_session; 115690e129ffSSebastian Andrzej Siewior 1157b7b61cbeSArnaldo Carvalho de Melo err = perf_session__process_events(session); 1158edbe9817SJiri Olsa if (!err) 115990e129ffSSebastian Andrzej Siewior err = ctf_writer__flush_streams(cw); 1160c2141055SHe Kuang else 1161c2141055SHe Kuang pr_err("Error during conversion.\n"); 1162edbe9817SJiri Olsa 1163edbe9817SJiri Olsa fprintf(stderr, 1164edbe9817SJiri Olsa "[ perf data convert: Converted '%s' into CTF data '%s' ]\n", 1165edbe9817SJiri Olsa file.path, path); 1166edbe9817SJiri Olsa 1167edbe9817SJiri Olsa fprintf(stderr, 1168edbe9817SJiri Olsa "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples) ]\n", 1169edbe9817SJiri Olsa (double) c.events_size / 1024.0 / 1024.0, 1170edbe9817SJiri Olsa c.events_count); 1171edbe9817SJiri Olsa 1172c2141055SHe Kuang perf_session__delete(session); 1173c2141055SHe Kuang ctf_writer__cleanup(cw); 1174c2141055SHe Kuang 1175c2141055SHe Kuang return err; 1176c2141055SHe Kuang 1177edbe9817SJiri Olsa free_session: 1178edbe9817SJiri Olsa perf_session__delete(session); 1179edbe9817SJiri Olsa free_writer: 1180edbe9817SJiri Olsa ctf_writer__cleanup(cw); 1181c2141055SHe Kuang pr_err("Error during conversion setup.\n"); 1182edbe9817SJiri Olsa return err; 1183edbe9817SJiri Olsa } 1184