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