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