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" 29f6c12a00SJiri Olsa #include "config.h" 30edbe9817SJiri Olsa 31edbe9817SJiri Olsa #define pr_N(n, fmt, ...) \ 32edbe9817SJiri Olsa eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__) 33edbe9817SJiri Olsa 34edbe9817SJiri Olsa #define pr(fmt, ...) pr_N(1, pr_fmt(fmt), ##__VA_ARGS__) 35edbe9817SJiri Olsa #define pr2(fmt, ...) pr_N(2, pr_fmt(fmt), ##__VA_ARGS__) 36edbe9817SJiri Olsa 37edbe9817SJiri Olsa #define pr_time2(t, fmt, ...) pr_time_N(2, debug_data_convert, t, pr_fmt(fmt), ##__VA_ARGS__) 38edbe9817SJiri Olsa 39edbe9817SJiri Olsa struct evsel_priv { 40edbe9817SJiri Olsa struct bt_ctf_event_class *event_class; 41edbe9817SJiri Olsa }; 42edbe9817SJiri Olsa 4390e129ffSSebastian Andrzej Siewior #define MAX_CPUS 4096 4490e129ffSSebastian Andrzej Siewior 4590e129ffSSebastian Andrzej Siewior struct ctf_stream { 4690e129ffSSebastian Andrzej Siewior struct bt_ctf_stream *stream; 4790e129ffSSebastian Andrzej Siewior int cpu; 4889e5fa88SJiri Olsa u32 count; 4990e129ffSSebastian Andrzej Siewior }; 5090e129ffSSebastian Andrzej Siewior 51edbe9817SJiri Olsa struct ctf_writer { 52edbe9817SJiri Olsa /* writer primitives */ 53edbe9817SJiri Olsa struct bt_ctf_writer *writer; 5490e129ffSSebastian Andrzej Siewior struct ctf_stream **stream; 5590e129ffSSebastian Andrzej Siewior int stream_cnt; 56edbe9817SJiri Olsa struct bt_ctf_stream_class *stream_class; 57edbe9817SJiri Olsa struct bt_ctf_clock *clock; 58edbe9817SJiri Olsa 59edbe9817SJiri Olsa /* data types */ 60edbe9817SJiri Olsa union { 61edbe9817SJiri Olsa struct { 62edbe9817SJiri Olsa struct bt_ctf_field_type *s64; 63edbe9817SJiri Olsa struct bt_ctf_field_type *u64; 64edbe9817SJiri Olsa struct bt_ctf_field_type *s32; 65edbe9817SJiri Olsa struct bt_ctf_field_type *u32; 66edbe9817SJiri Olsa struct bt_ctf_field_type *string; 6726812d46SWang Nan struct bt_ctf_field_type *u32_hex; 68edbe9817SJiri Olsa struct bt_ctf_field_type *u64_hex; 69edbe9817SJiri Olsa }; 70edbe9817SJiri Olsa struct bt_ctf_field_type *array[6]; 71edbe9817SJiri Olsa } data; 72*f5a08cedSWang Nan struct bt_ctf_event_class *comm_class; 73edbe9817SJiri Olsa }; 74edbe9817SJiri Olsa 75edbe9817SJiri Olsa struct convert { 76edbe9817SJiri Olsa struct perf_tool tool; 77edbe9817SJiri Olsa struct ctf_writer writer; 78edbe9817SJiri Olsa 79edbe9817SJiri Olsa u64 events_size; 80edbe9817SJiri Olsa u64 events_count; 818ee4c46cSWang Nan u64 non_sample_count; 828fa46753SJiri Olsa 838fa46753SJiri Olsa /* Ordered events configured queue size. */ 848fa46753SJiri Olsa u64 queue_size; 85edbe9817SJiri Olsa }; 86edbe9817SJiri Olsa 87edbe9817SJiri Olsa static int value_set(struct bt_ctf_field_type *type, 88edbe9817SJiri Olsa struct bt_ctf_event *event, 89edbe9817SJiri Olsa const char *name, u64 val) 90edbe9817SJiri Olsa { 91edbe9817SJiri Olsa struct bt_ctf_field *field; 92edbe9817SJiri Olsa bool sign = bt_ctf_field_type_integer_get_signed(type); 93edbe9817SJiri Olsa int ret; 94edbe9817SJiri Olsa 95edbe9817SJiri Olsa field = bt_ctf_field_create(type); 96edbe9817SJiri Olsa if (!field) { 97edbe9817SJiri Olsa pr_err("failed to create a field %s\n", name); 98edbe9817SJiri Olsa return -1; 99edbe9817SJiri Olsa } 100edbe9817SJiri Olsa 101edbe9817SJiri Olsa if (sign) { 102edbe9817SJiri Olsa ret = bt_ctf_field_signed_integer_set_value(field, val); 103edbe9817SJiri Olsa if (ret) { 104edbe9817SJiri Olsa pr_err("failed to set field value %s\n", name); 105edbe9817SJiri Olsa goto err; 106edbe9817SJiri Olsa } 107edbe9817SJiri Olsa } else { 108edbe9817SJiri Olsa ret = bt_ctf_field_unsigned_integer_set_value(field, val); 109edbe9817SJiri Olsa if (ret) { 110edbe9817SJiri Olsa pr_err("failed to set field value %s\n", name); 111edbe9817SJiri Olsa goto err; 112edbe9817SJiri Olsa } 113edbe9817SJiri Olsa } 114edbe9817SJiri Olsa 115edbe9817SJiri Olsa ret = bt_ctf_event_set_payload(event, name, field); 116edbe9817SJiri Olsa if (ret) { 117edbe9817SJiri Olsa pr_err("failed to set payload %s\n", name); 118edbe9817SJiri Olsa goto err; 119edbe9817SJiri Olsa } 120edbe9817SJiri Olsa 121edbe9817SJiri Olsa pr2(" SET [%s = %" PRIu64 "]\n", name, val); 122edbe9817SJiri Olsa 123edbe9817SJiri Olsa err: 124edbe9817SJiri Olsa bt_ctf_field_put(field); 125edbe9817SJiri Olsa return ret; 126edbe9817SJiri Olsa } 127edbe9817SJiri Olsa 128edbe9817SJiri Olsa #define __FUNC_VALUE_SET(_name, _val_type) \ 129edbe9817SJiri Olsa static __maybe_unused int value_set_##_name(struct ctf_writer *cw, \ 130edbe9817SJiri Olsa struct bt_ctf_event *event, \ 131edbe9817SJiri Olsa const char *name, \ 132edbe9817SJiri Olsa _val_type val) \ 133edbe9817SJiri Olsa { \ 134edbe9817SJiri Olsa struct bt_ctf_field_type *type = cw->data._name; \ 135edbe9817SJiri Olsa return value_set(type, event, name, (u64) val); \ 136edbe9817SJiri Olsa } 137edbe9817SJiri Olsa 138edbe9817SJiri Olsa #define FUNC_VALUE_SET(_name) __FUNC_VALUE_SET(_name, _name) 139edbe9817SJiri Olsa 140edbe9817SJiri Olsa FUNC_VALUE_SET(s32) 141edbe9817SJiri Olsa FUNC_VALUE_SET(u32) 142edbe9817SJiri Olsa FUNC_VALUE_SET(s64) 143edbe9817SJiri Olsa FUNC_VALUE_SET(u64) 144edbe9817SJiri Olsa __FUNC_VALUE_SET(u64_hex, u64) 145edbe9817SJiri Olsa 146069ee5c4SWang Nan static int string_set_value(struct bt_ctf_field *field, const char *string); 147069ee5c4SWang Nan static __maybe_unused int 148069ee5c4SWang Nan value_set_string(struct ctf_writer *cw, struct bt_ctf_event *event, 149069ee5c4SWang Nan const char *name, const char *string) 150069ee5c4SWang Nan { 151069ee5c4SWang Nan struct bt_ctf_field_type *type = cw->data.string; 152069ee5c4SWang Nan struct bt_ctf_field *field; 153069ee5c4SWang Nan int ret = 0; 154069ee5c4SWang Nan 155069ee5c4SWang Nan field = bt_ctf_field_create(type); 156069ee5c4SWang Nan if (!field) { 157069ee5c4SWang Nan pr_err("failed to create a field %s\n", name); 158069ee5c4SWang Nan return -1; 159069ee5c4SWang Nan } 160069ee5c4SWang Nan 161069ee5c4SWang Nan ret = string_set_value(field, string); 162069ee5c4SWang Nan if (ret) { 163069ee5c4SWang Nan pr_err("failed to set value %s\n", name); 164069ee5c4SWang Nan goto err_put_field; 165069ee5c4SWang Nan } 166069ee5c4SWang Nan 167069ee5c4SWang Nan ret = bt_ctf_event_set_payload(event, name, field); 168069ee5c4SWang Nan if (ret) 169069ee5c4SWang Nan pr_err("failed to set payload %s\n", name); 170069ee5c4SWang Nan 171069ee5c4SWang Nan err_put_field: 172069ee5c4SWang Nan bt_ctf_field_put(field); 173069ee5c4SWang Nan return ret; 174069ee5c4SWang Nan } 175069ee5c4SWang Nan 17669364727SSebastian Andrzej Siewior static struct bt_ctf_field_type* 17769364727SSebastian Andrzej Siewior get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field) 17869364727SSebastian Andrzej Siewior { 17969364727SSebastian Andrzej Siewior unsigned long flags = field->flags; 18069364727SSebastian Andrzej Siewior 18169364727SSebastian Andrzej Siewior if (flags & FIELD_IS_STRING) 18269364727SSebastian Andrzej Siewior return cw->data.string; 18369364727SSebastian Andrzej Siewior 18469364727SSebastian Andrzej Siewior if (!(flags & FIELD_IS_SIGNED)) { 18569364727SSebastian Andrzej Siewior /* unsigned long are mostly pointers */ 18669364727SSebastian Andrzej Siewior if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER) 18769364727SSebastian Andrzej Siewior return cw->data.u64_hex; 18869364727SSebastian Andrzej Siewior } 18969364727SSebastian Andrzej Siewior 19069364727SSebastian Andrzej Siewior if (flags & FIELD_IS_SIGNED) { 19169364727SSebastian Andrzej Siewior if (field->size == 8) 19269364727SSebastian Andrzej Siewior return cw->data.s64; 19369364727SSebastian Andrzej Siewior else 19469364727SSebastian Andrzej Siewior return cw->data.s32; 19569364727SSebastian Andrzej Siewior } 19669364727SSebastian Andrzej Siewior 19769364727SSebastian Andrzej Siewior if (field->size == 8) 19869364727SSebastian Andrzej Siewior return cw->data.u64; 19969364727SSebastian Andrzej Siewior else 20069364727SSebastian Andrzej Siewior return cw->data.u32; 20169364727SSebastian Andrzej Siewior } 20269364727SSebastian Andrzej Siewior 203d4ae4213SWang Nan static unsigned long long adjust_signedness(unsigned long long value_int, int size) 204d4ae4213SWang Nan { 205d4ae4213SWang Nan unsigned long long value_mask; 206d4ae4213SWang Nan 207d4ae4213SWang Nan /* 208d4ae4213SWang Nan * value_mask = (1 << (size * 8 - 1)) - 1. 209d4ae4213SWang Nan * Directly set value_mask for code readers. 210d4ae4213SWang Nan */ 211d4ae4213SWang Nan switch (size) { 212d4ae4213SWang Nan case 1: 213d4ae4213SWang Nan value_mask = 0x7fULL; 214d4ae4213SWang Nan break; 215d4ae4213SWang Nan case 2: 216d4ae4213SWang Nan value_mask = 0x7fffULL; 217d4ae4213SWang Nan break; 218d4ae4213SWang Nan case 4: 219d4ae4213SWang Nan value_mask = 0x7fffffffULL; 220d4ae4213SWang Nan break; 221d4ae4213SWang Nan case 8: 222d4ae4213SWang Nan /* 223d4ae4213SWang Nan * For 64 bit value, return it self. There is no need 224d4ae4213SWang Nan * to fill high bit. 225d4ae4213SWang Nan */ 226d4ae4213SWang Nan /* Fall through */ 227d4ae4213SWang Nan default: 228d4ae4213SWang Nan /* BUG! */ 229d4ae4213SWang Nan return value_int; 230d4ae4213SWang Nan } 231d4ae4213SWang Nan 232d4ae4213SWang Nan /* If it is a positive value, don't adjust. */ 233d4ae4213SWang Nan if ((value_int & (~0ULL - value_mask)) == 0) 234d4ae4213SWang Nan return value_int; 235d4ae4213SWang Nan 236d4ae4213SWang Nan /* Fill upper part of value_int with 1 to make it a negative long long. */ 237d4ae4213SWang Nan return (value_int & value_mask) | ~value_mask; 238d4ae4213SWang Nan } 239d4ae4213SWang Nan 2405ea5888bSWang Nan static int string_set_value(struct bt_ctf_field *field, const char *string) 2415ea5888bSWang Nan { 2425ea5888bSWang Nan char *buffer = NULL; 2435ea5888bSWang Nan size_t len = strlen(string), i, p; 2445ea5888bSWang Nan int err; 2455ea5888bSWang Nan 2465ea5888bSWang Nan for (i = p = 0; i < len; i++, p++) { 2475ea5888bSWang Nan if (isprint(string[i])) { 2485ea5888bSWang Nan if (!buffer) 2495ea5888bSWang Nan continue; 2505ea5888bSWang Nan buffer[p] = string[i]; 2515ea5888bSWang Nan } else { 2525ea5888bSWang Nan char numstr[5]; 2535ea5888bSWang Nan 2545ea5888bSWang Nan snprintf(numstr, sizeof(numstr), "\\x%02x", 2555ea5888bSWang Nan (unsigned int)(string[i]) & 0xff); 2565ea5888bSWang Nan 2575ea5888bSWang Nan if (!buffer) { 2585ea5888bSWang Nan buffer = zalloc(i + (len - i) * 4 + 2); 2595ea5888bSWang Nan if (!buffer) { 2605ea5888bSWang Nan pr_err("failed to set unprintable string '%s'\n", string); 2615ea5888bSWang Nan return bt_ctf_field_string_set_value(field, "UNPRINTABLE-STRING"); 2625ea5888bSWang Nan } 2635ea5888bSWang Nan if (i > 0) 2645ea5888bSWang Nan strncpy(buffer, string, i); 2655ea5888bSWang Nan } 2665ea5888bSWang Nan strncat(buffer + p, numstr, 4); 2675ea5888bSWang Nan p += 3; 2685ea5888bSWang Nan } 2695ea5888bSWang Nan } 2705ea5888bSWang Nan 2715ea5888bSWang Nan if (!buffer) 2725ea5888bSWang Nan return bt_ctf_field_string_set_value(field, string); 2735ea5888bSWang Nan err = bt_ctf_field_string_set_value(field, buffer); 2745ea5888bSWang Nan free(buffer); 2755ea5888bSWang Nan return err; 2765ea5888bSWang Nan } 2775ea5888bSWang Nan 27869364727SSebastian Andrzej Siewior static int add_tracepoint_field_value(struct ctf_writer *cw, 27969364727SSebastian Andrzej Siewior struct bt_ctf_event_class *event_class, 28069364727SSebastian Andrzej Siewior struct bt_ctf_event *event, 28169364727SSebastian Andrzej Siewior struct perf_sample *sample, 28269364727SSebastian Andrzej Siewior struct format_field *fmtf) 28369364727SSebastian Andrzej Siewior { 28469364727SSebastian Andrzej Siewior struct bt_ctf_field_type *type; 28569364727SSebastian Andrzej Siewior struct bt_ctf_field *array_field; 28669364727SSebastian Andrzej Siewior struct bt_ctf_field *field; 28769364727SSebastian Andrzej Siewior const char *name = fmtf->name; 28869364727SSebastian Andrzej Siewior void *data = sample->raw_data; 28969364727SSebastian Andrzej Siewior unsigned long flags = fmtf->flags; 29069364727SSebastian Andrzej Siewior unsigned int n_items; 29169364727SSebastian Andrzej Siewior unsigned int i; 29269364727SSebastian Andrzej Siewior unsigned int offset; 29369364727SSebastian Andrzej Siewior unsigned int len; 29469364727SSebastian Andrzej Siewior int ret; 29569364727SSebastian Andrzej Siewior 296e0a7cce5SWang Nan name = fmtf->alias; 29769364727SSebastian Andrzej Siewior offset = fmtf->offset; 29869364727SSebastian Andrzej Siewior len = fmtf->size; 29969364727SSebastian Andrzej Siewior if (flags & FIELD_IS_STRING) 30069364727SSebastian Andrzej Siewior flags &= ~FIELD_IS_ARRAY; 30169364727SSebastian Andrzej Siewior 30269364727SSebastian Andrzej Siewior if (flags & FIELD_IS_DYNAMIC) { 30369364727SSebastian Andrzej Siewior unsigned long long tmp_val; 30469364727SSebastian Andrzej Siewior 30569364727SSebastian Andrzej Siewior tmp_val = pevent_read_number(fmtf->event->pevent, 30669364727SSebastian Andrzej Siewior data + offset, len); 30769364727SSebastian Andrzej Siewior offset = tmp_val; 30869364727SSebastian Andrzej Siewior len = offset >> 16; 30969364727SSebastian Andrzej Siewior offset &= 0xffff; 31069364727SSebastian Andrzej Siewior } 31169364727SSebastian Andrzej Siewior 31269364727SSebastian Andrzej Siewior if (flags & FIELD_IS_ARRAY) { 31369364727SSebastian Andrzej Siewior 31469364727SSebastian Andrzej Siewior type = bt_ctf_event_class_get_field_by_name( 31569364727SSebastian Andrzej Siewior event_class, name); 31669364727SSebastian Andrzej Siewior array_field = bt_ctf_field_create(type); 31769364727SSebastian Andrzej Siewior bt_ctf_field_type_put(type); 31869364727SSebastian Andrzej Siewior if (!array_field) { 31969364727SSebastian Andrzej Siewior pr_err("Failed to create array type %s\n", name); 32069364727SSebastian Andrzej Siewior return -1; 32169364727SSebastian Andrzej Siewior } 32269364727SSebastian Andrzej Siewior 32369364727SSebastian Andrzej Siewior len = fmtf->size / fmtf->arraylen; 32469364727SSebastian Andrzej Siewior n_items = fmtf->arraylen; 32569364727SSebastian Andrzej Siewior } else { 32669364727SSebastian Andrzej Siewior n_items = 1; 32769364727SSebastian Andrzej Siewior array_field = NULL; 32869364727SSebastian Andrzej Siewior } 32969364727SSebastian Andrzej Siewior 33069364727SSebastian Andrzej Siewior type = get_tracepoint_field_type(cw, fmtf); 33169364727SSebastian Andrzej Siewior 33269364727SSebastian Andrzej Siewior for (i = 0; i < n_items; i++) { 33369364727SSebastian Andrzej Siewior if (flags & FIELD_IS_ARRAY) 33469364727SSebastian Andrzej Siewior field = bt_ctf_field_array_get_field(array_field, i); 33569364727SSebastian Andrzej Siewior else 33669364727SSebastian Andrzej Siewior field = bt_ctf_field_create(type); 33769364727SSebastian Andrzej Siewior 33869364727SSebastian Andrzej Siewior if (!field) { 33969364727SSebastian Andrzej Siewior pr_err("failed to create a field %s\n", name); 34069364727SSebastian Andrzej Siewior return -1; 34169364727SSebastian Andrzej Siewior } 34269364727SSebastian Andrzej Siewior 34369364727SSebastian Andrzej Siewior if (flags & FIELD_IS_STRING) 3445ea5888bSWang Nan ret = string_set_value(field, data + offset + i * len); 345d4ae4213SWang Nan else { 346d4ae4213SWang Nan unsigned long long value_int; 347d4ae4213SWang Nan 348d4ae4213SWang Nan value_int = pevent_read_number( 349d4ae4213SWang Nan fmtf->event->pevent, 350d4ae4213SWang Nan data + offset + i * len, len); 351d4ae4213SWang Nan 352d4ae4213SWang Nan if (!(flags & FIELD_IS_SIGNED)) 35369364727SSebastian Andrzej Siewior ret = bt_ctf_field_unsigned_integer_set_value( 35469364727SSebastian Andrzej Siewior field, value_int); 35569364727SSebastian Andrzej Siewior else 35669364727SSebastian Andrzej Siewior ret = bt_ctf_field_signed_integer_set_value( 357d4ae4213SWang Nan field, adjust_signedness(value_int, len)); 358d4ae4213SWang Nan } 359d4ae4213SWang Nan 36069364727SSebastian Andrzej Siewior if (ret) { 36169364727SSebastian Andrzej Siewior pr_err("failed to set file value %s\n", name); 36269364727SSebastian Andrzej Siewior goto err_put_field; 36369364727SSebastian Andrzej Siewior } 36469364727SSebastian Andrzej Siewior if (!(flags & FIELD_IS_ARRAY)) { 36569364727SSebastian Andrzej Siewior ret = bt_ctf_event_set_payload(event, name, field); 36669364727SSebastian Andrzej Siewior if (ret) { 36769364727SSebastian Andrzej Siewior pr_err("failed to set payload %s\n", name); 36869364727SSebastian Andrzej Siewior goto err_put_field; 36969364727SSebastian Andrzej Siewior } 37069364727SSebastian Andrzej Siewior } 37169364727SSebastian Andrzej Siewior bt_ctf_field_put(field); 37269364727SSebastian Andrzej Siewior } 37369364727SSebastian Andrzej Siewior if (flags & FIELD_IS_ARRAY) { 37469364727SSebastian Andrzej Siewior ret = bt_ctf_event_set_payload(event, name, array_field); 37569364727SSebastian Andrzej Siewior if (ret) { 37669364727SSebastian Andrzej Siewior pr_err("Failed add payload array %s\n", name); 37769364727SSebastian Andrzej Siewior return -1; 37869364727SSebastian Andrzej Siewior } 37969364727SSebastian Andrzej Siewior bt_ctf_field_put(array_field); 38069364727SSebastian Andrzej Siewior } 38169364727SSebastian Andrzej Siewior return 0; 38269364727SSebastian Andrzej Siewior 38369364727SSebastian Andrzej Siewior err_put_field: 38469364727SSebastian Andrzej Siewior bt_ctf_field_put(field); 38569364727SSebastian Andrzej Siewior return -1; 38669364727SSebastian Andrzej Siewior } 38769364727SSebastian Andrzej Siewior 38869364727SSebastian Andrzej Siewior static int add_tracepoint_fields_values(struct ctf_writer *cw, 38969364727SSebastian Andrzej Siewior struct bt_ctf_event_class *event_class, 39069364727SSebastian Andrzej Siewior struct bt_ctf_event *event, 39169364727SSebastian Andrzej Siewior struct format_field *fields, 39269364727SSebastian Andrzej Siewior struct perf_sample *sample) 39369364727SSebastian Andrzej Siewior { 39469364727SSebastian Andrzej Siewior struct format_field *field; 39569364727SSebastian Andrzej Siewior int ret; 39669364727SSebastian Andrzej Siewior 39769364727SSebastian Andrzej Siewior for (field = fields; field; field = field->next) { 39869364727SSebastian Andrzej Siewior ret = add_tracepoint_field_value(cw, event_class, event, sample, 39969364727SSebastian Andrzej Siewior field); 40069364727SSebastian Andrzej Siewior if (ret) 40169364727SSebastian Andrzej Siewior return -1; 40269364727SSebastian Andrzej Siewior } 40369364727SSebastian Andrzej Siewior return 0; 40469364727SSebastian Andrzej Siewior } 40569364727SSebastian Andrzej Siewior 40669364727SSebastian Andrzej Siewior static int add_tracepoint_values(struct ctf_writer *cw, 40769364727SSebastian Andrzej Siewior struct bt_ctf_event_class *event_class, 40869364727SSebastian Andrzej Siewior struct bt_ctf_event *event, 40969364727SSebastian Andrzej Siewior struct perf_evsel *evsel, 41069364727SSebastian Andrzej Siewior struct perf_sample *sample) 41169364727SSebastian Andrzej Siewior { 41269364727SSebastian Andrzej Siewior struct format_field *common_fields = evsel->tp_format->format.common_fields; 41369364727SSebastian Andrzej Siewior struct format_field *fields = evsel->tp_format->format.fields; 41469364727SSebastian Andrzej Siewior int ret; 41569364727SSebastian Andrzej Siewior 41669364727SSebastian Andrzej Siewior ret = add_tracepoint_fields_values(cw, event_class, event, 41769364727SSebastian Andrzej Siewior common_fields, sample); 41869364727SSebastian Andrzej Siewior if (!ret) 41969364727SSebastian Andrzej Siewior ret = add_tracepoint_fields_values(cw, event_class, event, 42069364727SSebastian Andrzej Siewior fields, sample); 42169364727SSebastian Andrzej Siewior 42269364727SSebastian Andrzej Siewior return ret; 42369364727SSebastian Andrzej Siewior } 42469364727SSebastian Andrzej Siewior 4256122d57eSWang Nan static int 4266122d57eSWang Nan add_bpf_output_values(struct bt_ctf_event_class *event_class, 4276122d57eSWang Nan struct bt_ctf_event *event, 4286122d57eSWang Nan struct perf_sample *sample) 4296122d57eSWang Nan { 4306122d57eSWang Nan struct bt_ctf_field_type *len_type, *seq_type; 4316122d57eSWang Nan struct bt_ctf_field *len_field, *seq_field; 4326122d57eSWang Nan unsigned int raw_size = sample->raw_size; 4336122d57eSWang Nan unsigned int nr_elements = raw_size / sizeof(u32); 4346122d57eSWang Nan unsigned int i; 4356122d57eSWang Nan int ret; 4366122d57eSWang Nan 4376122d57eSWang Nan if (nr_elements * sizeof(u32) != raw_size) 4386122d57eSWang Nan pr_warning("Incorrect raw_size (%u) in bpf output event, skip %lu bytes\n", 4396122d57eSWang Nan raw_size, nr_elements * sizeof(u32) - raw_size); 4406122d57eSWang Nan 4416122d57eSWang Nan len_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_len"); 4426122d57eSWang Nan len_field = bt_ctf_field_create(len_type); 4436122d57eSWang Nan if (!len_field) { 4446122d57eSWang Nan pr_err("failed to create 'raw_len' for bpf output event\n"); 4456122d57eSWang Nan ret = -1; 4466122d57eSWang Nan goto put_len_type; 4476122d57eSWang Nan } 4486122d57eSWang Nan 4496122d57eSWang Nan ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements); 4506122d57eSWang Nan if (ret) { 4516122d57eSWang Nan pr_err("failed to set field value for raw_len\n"); 4526122d57eSWang Nan goto put_len_field; 4536122d57eSWang Nan } 4546122d57eSWang Nan ret = bt_ctf_event_set_payload(event, "raw_len", len_field); 4556122d57eSWang Nan if (ret) { 4566122d57eSWang Nan pr_err("failed to set payload to raw_len\n"); 4576122d57eSWang Nan goto put_len_field; 4586122d57eSWang Nan } 4596122d57eSWang Nan 4606122d57eSWang Nan seq_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_data"); 4616122d57eSWang Nan seq_field = bt_ctf_field_create(seq_type); 4626122d57eSWang Nan if (!seq_field) { 4636122d57eSWang Nan pr_err("failed to create 'raw_data' for bpf output event\n"); 4646122d57eSWang Nan ret = -1; 4656122d57eSWang Nan goto put_seq_type; 4666122d57eSWang Nan } 4676122d57eSWang Nan 4686122d57eSWang Nan ret = bt_ctf_field_sequence_set_length(seq_field, len_field); 4696122d57eSWang Nan if (ret) { 4706122d57eSWang Nan pr_err("failed to set length of 'raw_data'\n"); 4716122d57eSWang Nan goto put_seq_field; 4726122d57eSWang Nan } 4736122d57eSWang Nan 4746122d57eSWang Nan for (i = 0; i < nr_elements; i++) { 4756122d57eSWang Nan struct bt_ctf_field *elem_field = 4766122d57eSWang Nan bt_ctf_field_sequence_get_field(seq_field, i); 4776122d57eSWang Nan 4786122d57eSWang Nan ret = bt_ctf_field_unsigned_integer_set_value(elem_field, 4796122d57eSWang Nan ((u32 *)(sample->raw_data))[i]); 4806122d57eSWang Nan 4816122d57eSWang Nan bt_ctf_field_put(elem_field); 4826122d57eSWang Nan if (ret) { 4836122d57eSWang Nan pr_err("failed to set raw_data[%d]\n", i); 4846122d57eSWang Nan goto put_seq_field; 4856122d57eSWang Nan } 4866122d57eSWang Nan } 4876122d57eSWang Nan 4886122d57eSWang Nan ret = bt_ctf_event_set_payload(event, "raw_data", seq_field); 4896122d57eSWang Nan if (ret) 4906122d57eSWang Nan pr_err("failed to set payload for raw_data\n"); 4916122d57eSWang Nan 4926122d57eSWang Nan put_seq_field: 4936122d57eSWang Nan bt_ctf_field_put(seq_field); 4946122d57eSWang Nan put_seq_type: 4956122d57eSWang Nan bt_ctf_field_type_put(seq_type); 4966122d57eSWang Nan put_len_field: 4976122d57eSWang Nan bt_ctf_field_put(len_field); 4986122d57eSWang Nan put_len_type: 4996122d57eSWang Nan bt_ctf_field_type_put(len_type); 5006122d57eSWang Nan return ret; 5016122d57eSWang Nan } 5026122d57eSWang Nan 503edbe9817SJiri Olsa static int add_generic_values(struct ctf_writer *cw, 504edbe9817SJiri Olsa struct bt_ctf_event *event, 505edbe9817SJiri Olsa struct perf_evsel *evsel, 506edbe9817SJiri Olsa struct perf_sample *sample) 507edbe9817SJiri Olsa { 508edbe9817SJiri Olsa u64 type = evsel->attr.sample_type; 509edbe9817SJiri Olsa int ret; 510edbe9817SJiri Olsa 511edbe9817SJiri Olsa /* 512edbe9817SJiri Olsa * missing: 513edbe9817SJiri Olsa * PERF_SAMPLE_TIME - not needed as we have it in 514edbe9817SJiri Olsa * ctf event header 515edbe9817SJiri Olsa * PERF_SAMPLE_READ - TODO 516edbe9817SJiri Olsa * PERF_SAMPLE_CALLCHAIN - TODO 517edbe9817SJiri Olsa * PERF_SAMPLE_RAW - tracepoint fields are handled separately 518edbe9817SJiri Olsa * PERF_SAMPLE_BRANCH_STACK - TODO 519edbe9817SJiri Olsa * PERF_SAMPLE_REGS_USER - TODO 520edbe9817SJiri Olsa * PERF_SAMPLE_STACK_USER - TODO 521edbe9817SJiri Olsa */ 522edbe9817SJiri Olsa 523edbe9817SJiri Olsa if (type & PERF_SAMPLE_IP) { 52454cf776aSSebastian Andrzej Siewior ret = value_set_u64_hex(cw, event, "perf_ip", sample->ip); 525edbe9817SJiri Olsa if (ret) 526edbe9817SJiri Olsa return -1; 527edbe9817SJiri Olsa } 528edbe9817SJiri Olsa 529edbe9817SJiri Olsa if (type & PERF_SAMPLE_TID) { 53054cf776aSSebastian Andrzej Siewior ret = value_set_s32(cw, event, "perf_tid", sample->tid); 531edbe9817SJiri Olsa if (ret) 532edbe9817SJiri Olsa return -1; 533edbe9817SJiri Olsa 53454cf776aSSebastian Andrzej Siewior ret = value_set_s32(cw, event, "perf_pid", sample->pid); 535edbe9817SJiri Olsa if (ret) 536edbe9817SJiri Olsa return -1; 537edbe9817SJiri Olsa } 538edbe9817SJiri Olsa 539edbe9817SJiri Olsa if ((type & PERF_SAMPLE_ID) || 540edbe9817SJiri Olsa (type & PERF_SAMPLE_IDENTIFIER)) { 54154cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_id", sample->id); 542edbe9817SJiri Olsa if (ret) 543edbe9817SJiri Olsa return -1; 544edbe9817SJiri Olsa } 545edbe9817SJiri Olsa 546edbe9817SJiri Olsa if (type & PERF_SAMPLE_STREAM_ID) { 54754cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_stream_id", sample->stream_id); 548edbe9817SJiri Olsa if (ret) 549edbe9817SJiri Olsa return -1; 550edbe9817SJiri Olsa } 551edbe9817SJiri Olsa 552edbe9817SJiri Olsa if (type & PERF_SAMPLE_PERIOD) { 55354cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_period", sample->period); 554edbe9817SJiri Olsa if (ret) 555edbe9817SJiri Olsa return -1; 556edbe9817SJiri Olsa } 557edbe9817SJiri Olsa 558edbe9817SJiri Olsa if (type & PERF_SAMPLE_WEIGHT) { 55954cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_weight", sample->weight); 560edbe9817SJiri Olsa if (ret) 561edbe9817SJiri Olsa return -1; 562edbe9817SJiri Olsa } 563edbe9817SJiri Olsa 564edbe9817SJiri Olsa if (type & PERF_SAMPLE_DATA_SRC) { 56554cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_data_src", 56654cf776aSSebastian Andrzej Siewior sample->data_src); 567edbe9817SJiri Olsa if (ret) 568edbe9817SJiri Olsa return -1; 569edbe9817SJiri Olsa } 570edbe9817SJiri Olsa 571edbe9817SJiri Olsa if (type & PERF_SAMPLE_TRANSACTION) { 57254cf776aSSebastian Andrzej Siewior ret = value_set_u64(cw, event, "perf_transaction", 57354cf776aSSebastian Andrzej Siewior sample->transaction); 574edbe9817SJiri Olsa if (ret) 575edbe9817SJiri Olsa return -1; 576edbe9817SJiri Olsa } 577edbe9817SJiri Olsa 578edbe9817SJiri Olsa return 0; 579edbe9817SJiri Olsa } 580edbe9817SJiri Olsa 58190e129ffSSebastian Andrzej Siewior static int ctf_stream__flush(struct ctf_stream *cs) 58290e129ffSSebastian Andrzej Siewior { 58390e129ffSSebastian Andrzej Siewior int err = 0; 58490e129ffSSebastian Andrzej Siewior 58590e129ffSSebastian Andrzej Siewior if (cs) { 58690e129ffSSebastian Andrzej Siewior err = bt_ctf_stream_flush(cs->stream); 58790e129ffSSebastian Andrzej Siewior if (err) 58890e129ffSSebastian Andrzej Siewior pr_err("CTF stream %d flush failed\n", cs->cpu); 58990e129ffSSebastian Andrzej Siewior 59089e5fa88SJiri Olsa pr("Flush stream for cpu %d (%u samples)\n", 59189e5fa88SJiri Olsa cs->cpu, cs->count); 59289e5fa88SJiri Olsa 59389e5fa88SJiri Olsa cs->count = 0; 59490e129ffSSebastian Andrzej Siewior } 59590e129ffSSebastian Andrzej Siewior 59690e129ffSSebastian Andrzej Siewior return err; 59790e129ffSSebastian Andrzej Siewior } 59890e129ffSSebastian Andrzej Siewior 59990e129ffSSebastian Andrzej Siewior static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu) 60090e129ffSSebastian Andrzej Siewior { 60190e129ffSSebastian Andrzej Siewior struct ctf_stream *cs; 60290e129ffSSebastian Andrzej Siewior struct bt_ctf_field *pkt_ctx = NULL; 60390e129ffSSebastian Andrzej Siewior struct bt_ctf_field *cpu_field = NULL; 60490e129ffSSebastian Andrzej Siewior struct bt_ctf_stream *stream = NULL; 60590e129ffSSebastian Andrzej Siewior int ret; 60690e129ffSSebastian Andrzej Siewior 60790e129ffSSebastian Andrzej Siewior cs = zalloc(sizeof(*cs)); 60890e129ffSSebastian Andrzej Siewior if (!cs) { 60990e129ffSSebastian Andrzej Siewior pr_err("Failed to allocate ctf stream\n"); 61090e129ffSSebastian Andrzej Siewior return NULL; 61190e129ffSSebastian Andrzej Siewior } 61290e129ffSSebastian Andrzej Siewior 61390e129ffSSebastian Andrzej Siewior stream = bt_ctf_writer_create_stream(cw->writer, cw->stream_class); 61490e129ffSSebastian Andrzej Siewior if (!stream) { 61590e129ffSSebastian Andrzej Siewior pr_err("Failed to create CTF stream\n"); 61690e129ffSSebastian Andrzej Siewior goto out; 61790e129ffSSebastian Andrzej Siewior } 61890e129ffSSebastian Andrzej Siewior 61990e129ffSSebastian Andrzej Siewior pkt_ctx = bt_ctf_stream_get_packet_context(stream); 62090e129ffSSebastian Andrzej Siewior if (!pkt_ctx) { 62190e129ffSSebastian Andrzej Siewior pr_err("Failed to obtain packet context\n"); 62290e129ffSSebastian Andrzej Siewior goto out; 62390e129ffSSebastian Andrzej Siewior } 62490e129ffSSebastian Andrzej Siewior 62590e129ffSSebastian Andrzej Siewior cpu_field = bt_ctf_field_structure_get_field(pkt_ctx, "cpu_id"); 62690e129ffSSebastian Andrzej Siewior bt_ctf_field_put(pkt_ctx); 62790e129ffSSebastian Andrzej Siewior if (!cpu_field) { 62890e129ffSSebastian Andrzej Siewior pr_err("Failed to obtain cpu field\n"); 62990e129ffSSebastian Andrzej Siewior goto out; 63090e129ffSSebastian Andrzej Siewior } 63190e129ffSSebastian Andrzej Siewior 63290e129ffSSebastian Andrzej Siewior ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu); 63390e129ffSSebastian Andrzej Siewior if (ret) { 63490e129ffSSebastian Andrzej Siewior pr_err("Failed to update CPU number\n"); 63590e129ffSSebastian Andrzej Siewior goto out; 63690e129ffSSebastian Andrzej Siewior } 63790e129ffSSebastian Andrzej Siewior 63890e129ffSSebastian Andrzej Siewior bt_ctf_field_put(cpu_field); 63990e129ffSSebastian Andrzej Siewior 64090e129ffSSebastian Andrzej Siewior cs->cpu = cpu; 64190e129ffSSebastian Andrzej Siewior cs->stream = stream; 64290e129ffSSebastian Andrzej Siewior return cs; 64390e129ffSSebastian Andrzej Siewior 64490e129ffSSebastian Andrzej Siewior out: 64590e129ffSSebastian Andrzej Siewior if (cpu_field) 64690e129ffSSebastian Andrzej Siewior bt_ctf_field_put(cpu_field); 64790e129ffSSebastian Andrzej Siewior if (stream) 64890e129ffSSebastian Andrzej Siewior bt_ctf_stream_put(stream); 64990e129ffSSebastian Andrzej Siewior 65090e129ffSSebastian Andrzej Siewior free(cs); 65190e129ffSSebastian Andrzej Siewior return NULL; 65290e129ffSSebastian Andrzej Siewior } 65390e129ffSSebastian Andrzej Siewior 65490e129ffSSebastian Andrzej Siewior static void ctf_stream__delete(struct ctf_stream *cs) 65590e129ffSSebastian Andrzej Siewior { 65690e129ffSSebastian Andrzej Siewior if (cs) { 65790e129ffSSebastian Andrzej Siewior bt_ctf_stream_put(cs->stream); 65890e129ffSSebastian Andrzej Siewior free(cs); 65990e129ffSSebastian Andrzej Siewior } 66090e129ffSSebastian Andrzej Siewior } 66190e129ffSSebastian Andrzej Siewior 66290e129ffSSebastian Andrzej Siewior static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu) 66390e129ffSSebastian Andrzej Siewior { 66490e129ffSSebastian Andrzej Siewior struct ctf_stream *cs = cw->stream[cpu]; 66590e129ffSSebastian Andrzej Siewior 66690e129ffSSebastian Andrzej Siewior if (!cs) { 66790e129ffSSebastian Andrzej Siewior cs = ctf_stream__create(cw, cpu); 66890e129ffSSebastian Andrzej Siewior cw->stream[cpu] = cs; 66990e129ffSSebastian Andrzej Siewior } 67090e129ffSSebastian Andrzej Siewior 67190e129ffSSebastian Andrzej Siewior return cs; 67290e129ffSSebastian Andrzej Siewior } 67390e129ffSSebastian Andrzej Siewior 67490e129ffSSebastian Andrzej Siewior static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample, 67590e129ffSSebastian Andrzej Siewior struct perf_evsel *evsel) 67690e129ffSSebastian Andrzej Siewior { 67790e129ffSSebastian Andrzej Siewior int cpu = 0; 67890e129ffSSebastian Andrzej Siewior 67990e129ffSSebastian Andrzej Siewior if (evsel->attr.sample_type & PERF_SAMPLE_CPU) 68090e129ffSSebastian Andrzej Siewior cpu = sample->cpu; 68190e129ffSSebastian Andrzej Siewior 68290e129ffSSebastian Andrzej Siewior if (cpu > cw->stream_cnt) { 68390e129ffSSebastian Andrzej Siewior pr_err("Event was recorded for CPU %d, limit is at %d.\n", 68490e129ffSSebastian Andrzej Siewior cpu, cw->stream_cnt); 68590e129ffSSebastian Andrzej Siewior cpu = 0; 68690e129ffSSebastian Andrzej Siewior } 68790e129ffSSebastian Andrzej Siewior 68890e129ffSSebastian Andrzej Siewior return cpu; 68990e129ffSSebastian Andrzej Siewior } 69090e129ffSSebastian Andrzej Siewior 69189e5fa88SJiri Olsa #define STREAM_FLUSH_COUNT 100000 69289e5fa88SJiri Olsa 69389e5fa88SJiri Olsa /* 69489e5fa88SJiri Olsa * Currently we have no other way to determine the 69589e5fa88SJiri Olsa * time for the stream flush other than keep track 69689e5fa88SJiri Olsa * of the number of events and check it against 69789e5fa88SJiri Olsa * threshold. 69889e5fa88SJiri Olsa */ 69989e5fa88SJiri Olsa static bool is_flush_needed(struct ctf_stream *cs) 70089e5fa88SJiri Olsa { 70189e5fa88SJiri Olsa return cs->count >= STREAM_FLUSH_COUNT; 70289e5fa88SJiri Olsa } 70389e5fa88SJiri Olsa 704edbe9817SJiri Olsa static int process_sample_event(struct perf_tool *tool, 705b8f8eb84SArnaldo Carvalho de Melo union perf_event *_event, 706edbe9817SJiri Olsa struct perf_sample *sample, 707edbe9817SJiri Olsa struct perf_evsel *evsel, 708edbe9817SJiri Olsa struct machine *machine __maybe_unused) 709edbe9817SJiri Olsa { 710edbe9817SJiri Olsa struct convert *c = container_of(tool, struct convert, tool); 711edbe9817SJiri Olsa struct evsel_priv *priv = evsel->priv; 712edbe9817SJiri Olsa struct ctf_writer *cw = &c->writer; 71390e129ffSSebastian Andrzej Siewior struct ctf_stream *cs; 714edbe9817SJiri Olsa struct bt_ctf_event_class *event_class; 715edbe9817SJiri Olsa struct bt_ctf_event *event; 716edbe9817SJiri Olsa int ret; 717edbe9817SJiri Olsa 718edbe9817SJiri Olsa if (WARN_ONCE(!priv, "Failed to setup all events.\n")) 719edbe9817SJiri Olsa return 0; 720edbe9817SJiri Olsa 721edbe9817SJiri Olsa event_class = priv->event_class; 722edbe9817SJiri Olsa 723edbe9817SJiri Olsa /* update stats */ 724edbe9817SJiri Olsa c->events_count++; 725edbe9817SJiri Olsa c->events_size += _event->header.size; 726edbe9817SJiri Olsa 727edbe9817SJiri Olsa pr_time2(sample->time, "sample %" PRIu64 "\n", c->events_count); 728edbe9817SJiri Olsa 729edbe9817SJiri Olsa event = bt_ctf_event_create(event_class); 730edbe9817SJiri Olsa if (!event) { 731edbe9817SJiri Olsa pr_err("Failed to create an CTF event\n"); 732edbe9817SJiri Olsa return -1; 733edbe9817SJiri Olsa } 734edbe9817SJiri Olsa 735edbe9817SJiri Olsa bt_ctf_clock_set_time(cw->clock, sample->time); 736edbe9817SJiri Olsa 737edbe9817SJiri Olsa ret = add_generic_values(cw, event, evsel, sample); 738edbe9817SJiri Olsa if (ret) 739edbe9817SJiri Olsa return -1; 740edbe9817SJiri Olsa 74169364727SSebastian Andrzej Siewior if (evsel->attr.type == PERF_TYPE_TRACEPOINT) { 74269364727SSebastian Andrzej Siewior ret = add_tracepoint_values(cw, event_class, event, 74369364727SSebastian Andrzej Siewior evsel, sample); 74469364727SSebastian Andrzej Siewior if (ret) 74569364727SSebastian Andrzej Siewior return -1; 74669364727SSebastian Andrzej Siewior } 74769364727SSebastian Andrzej Siewior 7486122d57eSWang Nan if (perf_evsel__is_bpf_output(evsel)) { 7496122d57eSWang Nan ret = add_bpf_output_values(event_class, event, sample); 7506122d57eSWang Nan if (ret) 7516122d57eSWang Nan return -1; 7526122d57eSWang Nan } 7536122d57eSWang Nan 75490e129ffSSebastian Andrzej Siewior cs = ctf_stream(cw, get_sample_cpu(cw, sample, evsel)); 75589e5fa88SJiri Olsa if (cs) { 75689e5fa88SJiri Olsa if (is_flush_needed(cs)) 75789e5fa88SJiri Olsa ctf_stream__flush(cs); 75889e5fa88SJiri Olsa 75989e5fa88SJiri Olsa cs->count++; 76090e129ffSSebastian Andrzej Siewior bt_ctf_stream_append_event(cs->stream, event); 76189e5fa88SJiri Olsa } 76290e129ffSSebastian Andrzej Siewior 763edbe9817SJiri Olsa bt_ctf_event_put(event); 76490e129ffSSebastian Andrzej Siewior return cs ? 0 : -1; 765edbe9817SJiri Olsa } 766edbe9817SJiri Olsa 767*f5a08cedSWang Nan #define __NON_SAMPLE_SET_FIELD(_name, _type, _field) \ 768*f5a08cedSWang Nan do { \ 769*f5a08cedSWang Nan ret = value_set_##_type(cw, event, #_field, _event->_name._field);\ 770*f5a08cedSWang Nan if (ret) \ 771*f5a08cedSWang Nan return -1; \ 772*f5a08cedSWang Nan } while(0) 773*f5a08cedSWang Nan 774*f5a08cedSWang Nan #define __FUNC_PROCESS_NON_SAMPLE(_name, body) \ 775*f5a08cedSWang Nan static int process_##_name##_event(struct perf_tool *tool, \ 776*f5a08cedSWang Nan union perf_event *_event, \ 777*f5a08cedSWang Nan struct perf_sample *sample, \ 778*f5a08cedSWang Nan struct machine *machine) \ 779*f5a08cedSWang Nan { \ 780*f5a08cedSWang Nan struct convert *c = container_of(tool, struct convert, tool);\ 781*f5a08cedSWang Nan struct ctf_writer *cw = &c->writer; \ 782*f5a08cedSWang Nan struct bt_ctf_event_class *event_class = cw->_name##_class;\ 783*f5a08cedSWang Nan struct bt_ctf_event *event; \ 784*f5a08cedSWang Nan struct ctf_stream *cs; \ 785*f5a08cedSWang Nan int ret; \ 786*f5a08cedSWang Nan \ 787*f5a08cedSWang Nan c->non_sample_count++; \ 788*f5a08cedSWang Nan c->events_size += _event->header.size; \ 789*f5a08cedSWang Nan event = bt_ctf_event_create(event_class); \ 790*f5a08cedSWang Nan if (!event) { \ 791*f5a08cedSWang Nan pr_err("Failed to create an CTF event\n"); \ 792*f5a08cedSWang Nan return -1; \ 793*f5a08cedSWang Nan } \ 794*f5a08cedSWang Nan \ 795*f5a08cedSWang Nan bt_ctf_clock_set_time(cw->clock, sample->time); \ 796*f5a08cedSWang Nan body \ 797*f5a08cedSWang Nan cs = ctf_stream(cw, 0); \ 798*f5a08cedSWang Nan if (cs) { \ 799*f5a08cedSWang Nan if (is_flush_needed(cs)) \ 800*f5a08cedSWang Nan ctf_stream__flush(cs); \ 801*f5a08cedSWang Nan \ 802*f5a08cedSWang Nan cs->count++; \ 803*f5a08cedSWang Nan bt_ctf_stream_append_event(cs->stream, event); \ 804*f5a08cedSWang Nan } \ 805*f5a08cedSWang Nan bt_ctf_event_put(event); \ 806*f5a08cedSWang Nan \ 807*f5a08cedSWang Nan return perf_event__process_##_name(tool, _event, sample, machine);\ 808*f5a08cedSWang Nan } 809*f5a08cedSWang Nan 810*f5a08cedSWang Nan __FUNC_PROCESS_NON_SAMPLE(comm, 811*f5a08cedSWang Nan __NON_SAMPLE_SET_FIELD(comm, u32, pid); 812*f5a08cedSWang Nan __NON_SAMPLE_SET_FIELD(comm, u32, tid); 813*f5a08cedSWang Nan __NON_SAMPLE_SET_FIELD(comm, string, comm); 814*f5a08cedSWang Nan ) 815*f5a08cedSWang Nan #undef __NON_SAMPLE_SET_FIELD 816*f5a08cedSWang Nan #undef __FUNC_PROCESS_NON_SAMPLE 817*f5a08cedSWang Nan 818e0a7cce5SWang Nan /* If dup < 0, add a prefix. Else, add _dupl_X suffix. */ 819e0a7cce5SWang Nan static char *change_name(char *name, char *orig_name, int dup) 820e0a7cce5SWang Nan { 821e0a7cce5SWang Nan char *new_name = NULL; 822e0a7cce5SWang Nan size_t len; 823e0a7cce5SWang Nan 824e0a7cce5SWang Nan if (!name) 825e0a7cce5SWang Nan name = orig_name; 826e0a7cce5SWang Nan 827e0a7cce5SWang Nan if (dup >= 10) 828e0a7cce5SWang Nan goto out; 829e0a7cce5SWang Nan /* 830e0a7cce5SWang Nan * Add '_' prefix to potential keywork. According to 831e0a7cce5SWang Nan * Mathieu Desnoyers (https://lkml.org/lkml/2015/1/23/652), 832e0a7cce5SWang Nan * futher CTF spec updating may require us to use '$'. 833e0a7cce5SWang Nan */ 834e0a7cce5SWang Nan if (dup < 0) 835e0a7cce5SWang Nan len = strlen(name) + sizeof("_"); 836e0a7cce5SWang Nan else 837e0a7cce5SWang Nan len = strlen(orig_name) + sizeof("_dupl_X"); 838e0a7cce5SWang Nan 839e0a7cce5SWang Nan new_name = malloc(len); 840e0a7cce5SWang Nan if (!new_name) 841e0a7cce5SWang Nan goto out; 842e0a7cce5SWang Nan 843e0a7cce5SWang Nan if (dup < 0) 844e0a7cce5SWang Nan snprintf(new_name, len, "_%s", name); 845e0a7cce5SWang Nan else 846e0a7cce5SWang Nan snprintf(new_name, len, "%s_dupl_%d", orig_name, dup); 847e0a7cce5SWang Nan 848e0a7cce5SWang Nan out: 849e0a7cce5SWang Nan if (name != orig_name) 850e0a7cce5SWang Nan free(name); 851e0a7cce5SWang Nan return new_name; 852e0a7cce5SWang Nan } 853e0a7cce5SWang Nan 854e0a7cce5SWang Nan static int event_class_add_field(struct bt_ctf_event_class *event_class, 855e0a7cce5SWang Nan struct bt_ctf_field_type *type, 856e0a7cce5SWang Nan struct format_field *field) 857e0a7cce5SWang Nan { 858e0a7cce5SWang Nan struct bt_ctf_field_type *t = NULL; 859e0a7cce5SWang Nan char *name; 860e0a7cce5SWang Nan int dup = 1; 861e0a7cce5SWang Nan int ret; 862e0a7cce5SWang Nan 863e0a7cce5SWang Nan /* alias was already assigned */ 864e0a7cce5SWang Nan if (field->alias != field->name) 865e0a7cce5SWang Nan return bt_ctf_event_class_add_field(event_class, type, 866e0a7cce5SWang Nan (char *)field->alias); 867e0a7cce5SWang Nan 868e0a7cce5SWang Nan name = field->name; 869e0a7cce5SWang Nan 870e0a7cce5SWang Nan /* If 'name' is a keywork, add prefix. */ 871e0a7cce5SWang Nan if (bt_ctf_validate_identifier(name)) 872e0a7cce5SWang Nan name = change_name(name, field->name, -1); 873e0a7cce5SWang Nan 874e0a7cce5SWang Nan if (!name) { 875e0a7cce5SWang Nan pr_err("Failed to fix invalid identifier."); 876e0a7cce5SWang Nan return -1; 877e0a7cce5SWang Nan } 878e0a7cce5SWang Nan while ((t = bt_ctf_event_class_get_field_by_name(event_class, name))) { 879e0a7cce5SWang Nan bt_ctf_field_type_put(t); 880e0a7cce5SWang Nan name = change_name(name, field->name, dup++); 881e0a7cce5SWang Nan if (!name) { 882e0a7cce5SWang Nan pr_err("Failed to create dup name for '%s'\n", field->name); 883e0a7cce5SWang Nan return -1; 884e0a7cce5SWang Nan } 885e0a7cce5SWang Nan } 886e0a7cce5SWang Nan 887e0a7cce5SWang Nan ret = bt_ctf_event_class_add_field(event_class, type, name); 888e0a7cce5SWang Nan if (!ret) 889e0a7cce5SWang Nan field->alias = name; 890e0a7cce5SWang Nan 891e0a7cce5SWang Nan return ret; 892e0a7cce5SWang Nan } 893e0a7cce5SWang Nan 89469364727SSebastian Andrzej Siewior static int add_tracepoint_fields_types(struct ctf_writer *cw, 89569364727SSebastian Andrzej Siewior struct format_field *fields, 89669364727SSebastian Andrzej Siewior struct bt_ctf_event_class *event_class) 89769364727SSebastian Andrzej Siewior { 89869364727SSebastian Andrzej Siewior struct format_field *field; 89969364727SSebastian Andrzej Siewior int ret; 90069364727SSebastian Andrzej Siewior 90169364727SSebastian Andrzej Siewior for (field = fields; field; field = field->next) { 90269364727SSebastian Andrzej Siewior struct bt_ctf_field_type *type; 90369364727SSebastian Andrzej Siewior unsigned long flags = field->flags; 90469364727SSebastian Andrzej Siewior 90569364727SSebastian Andrzej Siewior pr2(" field '%s'\n", field->name); 90669364727SSebastian Andrzej Siewior 90769364727SSebastian Andrzej Siewior type = get_tracepoint_field_type(cw, field); 90869364727SSebastian Andrzej Siewior if (!type) 90969364727SSebastian Andrzej Siewior return -1; 91069364727SSebastian Andrzej Siewior 91169364727SSebastian Andrzej Siewior /* 91269364727SSebastian Andrzej Siewior * A string is an array of chars. For this we use the string 91369364727SSebastian Andrzej Siewior * type and don't care that it is an array. What we don't 91469364727SSebastian Andrzej Siewior * support is an array of strings. 91569364727SSebastian Andrzej Siewior */ 91669364727SSebastian Andrzej Siewior if (flags & FIELD_IS_STRING) 91769364727SSebastian Andrzej Siewior flags &= ~FIELD_IS_ARRAY; 91869364727SSebastian Andrzej Siewior 91969364727SSebastian Andrzej Siewior if (flags & FIELD_IS_ARRAY) 92069364727SSebastian Andrzej Siewior type = bt_ctf_field_type_array_create(type, field->arraylen); 92169364727SSebastian Andrzej Siewior 922e0a7cce5SWang Nan ret = event_class_add_field(event_class, type, field); 92369364727SSebastian Andrzej Siewior 92469364727SSebastian Andrzej Siewior if (flags & FIELD_IS_ARRAY) 92569364727SSebastian Andrzej Siewior bt_ctf_field_type_put(type); 92669364727SSebastian Andrzej Siewior 92769364727SSebastian Andrzej Siewior if (ret) { 928e0a7cce5SWang Nan pr_err("Failed to add field '%s': %d\n", 929e0a7cce5SWang Nan field->name, ret); 93069364727SSebastian Andrzej Siewior return -1; 93169364727SSebastian Andrzej Siewior } 93269364727SSebastian Andrzej Siewior } 93369364727SSebastian Andrzej Siewior 93469364727SSebastian Andrzej Siewior return 0; 93569364727SSebastian Andrzej Siewior } 93669364727SSebastian Andrzej Siewior 93769364727SSebastian Andrzej Siewior static int add_tracepoint_types(struct ctf_writer *cw, 93869364727SSebastian Andrzej Siewior struct perf_evsel *evsel, 93969364727SSebastian Andrzej Siewior struct bt_ctf_event_class *class) 94069364727SSebastian Andrzej Siewior { 94169364727SSebastian Andrzej Siewior struct format_field *common_fields = evsel->tp_format->format.common_fields; 94269364727SSebastian Andrzej Siewior struct format_field *fields = evsel->tp_format->format.fields; 94369364727SSebastian Andrzej Siewior int ret; 94469364727SSebastian Andrzej Siewior 94569364727SSebastian Andrzej Siewior ret = add_tracepoint_fields_types(cw, common_fields, class); 94669364727SSebastian Andrzej Siewior if (!ret) 94769364727SSebastian Andrzej Siewior ret = add_tracepoint_fields_types(cw, fields, class); 94869364727SSebastian Andrzej Siewior 94969364727SSebastian Andrzej Siewior return ret; 95069364727SSebastian Andrzej Siewior } 95169364727SSebastian Andrzej Siewior 9526122d57eSWang Nan static int add_bpf_output_types(struct ctf_writer *cw, 9536122d57eSWang Nan struct bt_ctf_event_class *class) 9546122d57eSWang Nan { 9556122d57eSWang Nan struct bt_ctf_field_type *len_type = cw->data.u32; 9566122d57eSWang Nan struct bt_ctf_field_type *seq_base_type = cw->data.u32_hex; 9576122d57eSWang Nan struct bt_ctf_field_type *seq_type; 9586122d57eSWang Nan int ret; 9596122d57eSWang Nan 9606122d57eSWang Nan ret = bt_ctf_event_class_add_field(class, len_type, "raw_len"); 9616122d57eSWang Nan if (ret) 9626122d57eSWang Nan return ret; 9636122d57eSWang Nan 9646122d57eSWang Nan seq_type = bt_ctf_field_type_sequence_create(seq_base_type, "raw_len"); 9656122d57eSWang Nan if (!seq_type) 9666122d57eSWang Nan return -1; 9676122d57eSWang Nan 9686122d57eSWang Nan return bt_ctf_event_class_add_field(class, seq_type, "raw_data"); 9696122d57eSWang Nan } 9706122d57eSWang Nan 971edbe9817SJiri Olsa static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel, 972edbe9817SJiri Olsa struct bt_ctf_event_class *event_class) 973edbe9817SJiri Olsa { 974edbe9817SJiri Olsa u64 type = evsel->attr.sample_type; 975edbe9817SJiri Olsa 976edbe9817SJiri Olsa /* 977edbe9817SJiri Olsa * missing: 978edbe9817SJiri Olsa * PERF_SAMPLE_TIME - not needed as we have it in 979edbe9817SJiri Olsa * ctf event header 980edbe9817SJiri Olsa * PERF_SAMPLE_READ - TODO 981edbe9817SJiri Olsa * PERF_SAMPLE_CALLCHAIN - TODO 9826122d57eSWang Nan * PERF_SAMPLE_RAW - tracepoint fields and BPF output 9836122d57eSWang Nan * are handled separately 984edbe9817SJiri Olsa * PERF_SAMPLE_BRANCH_STACK - TODO 985edbe9817SJiri Olsa * PERF_SAMPLE_REGS_USER - TODO 986edbe9817SJiri Olsa * PERF_SAMPLE_STACK_USER - TODO 987edbe9817SJiri Olsa */ 988edbe9817SJiri Olsa 989edbe9817SJiri Olsa #define ADD_FIELD(cl, t, n) \ 990edbe9817SJiri Olsa do { \ 991edbe9817SJiri Olsa pr2(" field '%s'\n", n); \ 992edbe9817SJiri Olsa if (bt_ctf_event_class_add_field(cl, t, n)) { \ 993e0a7cce5SWang Nan pr_err("Failed to add field '%s';\n", n); \ 994edbe9817SJiri Olsa return -1; \ 995edbe9817SJiri Olsa } \ 996edbe9817SJiri Olsa } while (0) 997edbe9817SJiri Olsa 998edbe9817SJiri Olsa if (type & PERF_SAMPLE_IP) 99954cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64_hex, "perf_ip"); 1000edbe9817SJiri Olsa 1001edbe9817SJiri Olsa if (type & PERF_SAMPLE_TID) { 100254cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.s32, "perf_tid"); 100354cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.s32, "perf_pid"); 1004edbe9817SJiri Olsa } 1005edbe9817SJiri Olsa 1006edbe9817SJiri Olsa if ((type & PERF_SAMPLE_ID) || 1007edbe9817SJiri Olsa (type & PERF_SAMPLE_IDENTIFIER)) 100854cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_id"); 1009edbe9817SJiri Olsa 1010edbe9817SJiri Olsa if (type & PERF_SAMPLE_STREAM_ID) 101154cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_stream_id"); 1012edbe9817SJiri Olsa 1013edbe9817SJiri Olsa if (type & PERF_SAMPLE_PERIOD) 101454cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_period"); 1015edbe9817SJiri Olsa 1016edbe9817SJiri Olsa if (type & PERF_SAMPLE_WEIGHT) 101754cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_weight"); 1018edbe9817SJiri Olsa 1019edbe9817SJiri Olsa if (type & PERF_SAMPLE_DATA_SRC) 102054cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_data_src"); 1021edbe9817SJiri Olsa 1022edbe9817SJiri Olsa if (type & PERF_SAMPLE_TRANSACTION) 102354cf776aSSebastian Andrzej Siewior ADD_FIELD(event_class, cw->data.u64, "perf_transaction"); 1024edbe9817SJiri Olsa 1025edbe9817SJiri Olsa #undef ADD_FIELD 1026edbe9817SJiri Olsa return 0; 1027edbe9817SJiri Olsa } 1028edbe9817SJiri Olsa 1029edbe9817SJiri Olsa static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel) 1030edbe9817SJiri Olsa { 1031edbe9817SJiri Olsa struct bt_ctf_event_class *event_class; 1032edbe9817SJiri Olsa struct evsel_priv *priv; 1033edbe9817SJiri Olsa const char *name = perf_evsel__name(evsel); 1034edbe9817SJiri Olsa int ret; 1035edbe9817SJiri Olsa 1036edbe9817SJiri Olsa pr("Adding event '%s' (type %d)\n", name, evsel->attr.type); 1037edbe9817SJiri Olsa 1038edbe9817SJiri Olsa event_class = bt_ctf_event_class_create(name); 1039edbe9817SJiri Olsa if (!event_class) 1040edbe9817SJiri Olsa return -1; 1041edbe9817SJiri Olsa 1042edbe9817SJiri Olsa ret = add_generic_types(cw, evsel, event_class); 1043edbe9817SJiri Olsa if (ret) 1044edbe9817SJiri Olsa goto err; 1045edbe9817SJiri Olsa 104669364727SSebastian Andrzej Siewior if (evsel->attr.type == PERF_TYPE_TRACEPOINT) { 104769364727SSebastian Andrzej Siewior ret = add_tracepoint_types(cw, evsel, event_class); 104869364727SSebastian Andrzej Siewior if (ret) 104969364727SSebastian Andrzej Siewior goto err; 105069364727SSebastian Andrzej Siewior } 105169364727SSebastian Andrzej Siewior 10526122d57eSWang Nan if (perf_evsel__is_bpf_output(evsel)) { 10536122d57eSWang Nan ret = add_bpf_output_types(cw, event_class); 10546122d57eSWang Nan if (ret) 10556122d57eSWang Nan goto err; 10566122d57eSWang Nan } 10576122d57eSWang Nan 1058edbe9817SJiri Olsa ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class); 1059edbe9817SJiri Olsa if (ret) { 1060edbe9817SJiri Olsa pr("Failed to add event class into stream.\n"); 1061edbe9817SJiri Olsa goto err; 1062edbe9817SJiri Olsa } 1063edbe9817SJiri Olsa 1064edbe9817SJiri Olsa priv = malloc(sizeof(*priv)); 1065edbe9817SJiri Olsa if (!priv) 1066edbe9817SJiri Olsa goto err; 1067edbe9817SJiri Olsa 1068edbe9817SJiri Olsa priv->event_class = event_class; 1069edbe9817SJiri Olsa evsel->priv = priv; 1070edbe9817SJiri Olsa return 0; 1071edbe9817SJiri Olsa 1072edbe9817SJiri Olsa err: 1073edbe9817SJiri Olsa bt_ctf_event_class_put(event_class); 1074edbe9817SJiri Olsa pr_err("Failed to add event '%s'.\n", name); 1075edbe9817SJiri Olsa return -1; 1076edbe9817SJiri Olsa } 1077edbe9817SJiri Olsa 1078edbe9817SJiri Olsa static int setup_events(struct ctf_writer *cw, struct perf_session *session) 1079edbe9817SJiri Olsa { 1080edbe9817SJiri Olsa struct perf_evlist *evlist = session->evlist; 1081edbe9817SJiri Olsa struct perf_evsel *evsel; 1082edbe9817SJiri Olsa int ret; 1083edbe9817SJiri Olsa 1084e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evlist, evsel) { 1085edbe9817SJiri Olsa ret = add_event(cw, evsel); 1086edbe9817SJiri Olsa if (ret) 1087edbe9817SJiri Olsa return ret; 1088edbe9817SJiri Olsa } 1089edbe9817SJiri Olsa return 0; 1090edbe9817SJiri Olsa } 1091edbe9817SJiri Olsa 1092*f5a08cedSWang Nan #define __NON_SAMPLE_ADD_FIELD(t, n) \ 1093*f5a08cedSWang Nan do { \ 1094*f5a08cedSWang Nan pr2(" field '%s'\n", #n); \ 1095*f5a08cedSWang Nan if (bt_ctf_event_class_add_field(event_class, cw->data.t, #n)) {\ 1096*f5a08cedSWang Nan pr_err("Failed to add field '%s';\n", #n);\ 1097*f5a08cedSWang Nan return -1; \ 1098*f5a08cedSWang Nan } \ 1099*f5a08cedSWang Nan } while(0) 1100*f5a08cedSWang Nan 1101*f5a08cedSWang Nan #define __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(_name, body) \ 1102*f5a08cedSWang Nan static int add_##_name##_event(struct ctf_writer *cw) \ 1103*f5a08cedSWang Nan { \ 1104*f5a08cedSWang Nan struct bt_ctf_event_class *event_class; \ 1105*f5a08cedSWang Nan int ret; \ 1106*f5a08cedSWang Nan \ 1107*f5a08cedSWang Nan pr("Adding "#_name" event\n"); \ 1108*f5a08cedSWang Nan event_class = bt_ctf_event_class_create("perf_" #_name);\ 1109*f5a08cedSWang Nan if (!event_class) \ 1110*f5a08cedSWang Nan return -1; \ 1111*f5a08cedSWang Nan body \ 1112*f5a08cedSWang Nan \ 1113*f5a08cedSWang Nan ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);\ 1114*f5a08cedSWang Nan if (ret) { \ 1115*f5a08cedSWang Nan pr("Failed to add event class '"#_name"' into stream.\n");\ 1116*f5a08cedSWang Nan return ret; \ 1117*f5a08cedSWang Nan } \ 1118*f5a08cedSWang Nan \ 1119*f5a08cedSWang Nan cw->_name##_class = event_class; \ 1120*f5a08cedSWang Nan bt_ctf_event_class_put(event_class); \ 1121*f5a08cedSWang Nan return 0; \ 1122*f5a08cedSWang Nan } 1123*f5a08cedSWang Nan 1124*f5a08cedSWang Nan __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(comm, 1125*f5a08cedSWang Nan __NON_SAMPLE_ADD_FIELD(u32, pid); 1126*f5a08cedSWang Nan __NON_SAMPLE_ADD_FIELD(u32, tid); 1127*f5a08cedSWang Nan __NON_SAMPLE_ADD_FIELD(string, comm); 1128*f5a08cedSWang Nan ) 1129*f5a08cedSWang Nan 1130*f5a08cedSWang Nan #undef __NON_SAMPLE_ADD_FIELD 1131*f5a08cedSWang Nan #undef __FUNC_ADD_NON_SAMPLE_EVENT_CLASS 1132*f5a08cedSWang Nan 1133*f5a08cedSWang Nan static int setup_non_sample_events(struct ctf_writer *cw, 1134*f5a08cedSWang Nan struct perf_session *session __maybe_unused) 1135*f5a08cedSWang Nan { 1136*f5a08cedSWang Nan int ret; 1137*f5a08cedSWang Nan 1138*f5a08cedSWang Nan ret = add_comm_event(cw); 1139*f5a08cedSWang Nan if (ret) 1140*f5a08cedSWang Nan return ret; 1141*f5a08cedSWang Nan return 0; 1142*f5a08cedSWang Nan } 1143*f5a08cedSWang Nan 11445141d735SWang Nan static void cleanup_events(struct perf_session *session) 11455141d735SWang Nan { 11465141d735SWang Nan struct perf_evlist *evlist = session->evlist; 11475141d735SWang Nan struct perf_evsel *evsel; 11485141d735SWang Nan 1149e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evlist, evsel) { 11505141d735SWang Nan struct evsel_priv *priv; 11515141d735SWang Nan 11525141d735SWang Nan priv = evsel->priv; 11535141d735SWang Nan bt_ctf_event_class_put(priv->event_class); 11545141d735SWang Nan zfree(&evsel->priv); 11555141d735SWang Nan } 11565141d735SWang Nan 11575141d735SWang Nan perf_evlist__delete(evlist); 11585141d735SWang Nan session->evlist = NULL; 11595141d735SWang Nan } 11605141d735SWang Nan 116190e129ffSSebastian Andrzej Siewior static int setup_streams(struct ctf_writer *cw, struct perf_session *session) 116290e129ffSSebastian Andrzej Siewior { 116390e129ffSSebastian Andrzej Siewior struct ctf_stream **stream; 116490e129ffSSebastian Andrzej Siewior struct perf_header *ph = &session->header; 116590e129ffSSebastian Andrzej Siewior int ncpus; 116690e129ffSSebastian Andrzej Siewior 116790e129ffSSebastian Andrzej Siewior /* 116890e129ffSSebastian Andrzej Siewior * Try to get the number of cpus used in the data file, 116990e129ffSSebastian Andrzej Siewior * if not present fallback to the MAX_CPUS. 117090e129ffSSebastian Andrzej Siewior */ 117190e129ffSSebastian Andrzej Siewior ncpus = ph->env.nr_cpus_avail ?: MAX_CPUS; 117290e129ffSSebastian Andrzej Siewior 117390e129ffSSebastian Andrzej Siewior stream = zalloc(sizeof(*stream) * ncpus); 117490e129ffSSebastian Andrzej Siewior if (!stream) { 117590e129ffSSebastian Andrzej Siewior pr_err("Failed to allocate streams.\n"); 117690e129ffSSebastian Andrzej Siewior return -ENOMEM; 117790e129ffSSebastian Andrzej Siewior } 117890e129ffSSebastian Andrzej Siewior 117990e129ffSSebastian Andrzej Siewior cw->stream = stream; 118090e129ffSSebastian Andrzej Siewior cw->stream_cnt = ncpus; 118190e129ffSSebastian Andrzej Siewior return 0; 118290e129ffSSebastian Andrzej Siewior } 118390e129ffSSebastian Andrzej Siewior 118490e129ffSSebastian Andrzej Siewior static void free_streams(struct ctf_writer *cw) 118590e129ffSSebastian Andrzej Siewior { 118690e129ffSSebastian Andrzej Siewior int cpu; 118790e129ffSSebastian Andrzej Siewior 118890e129ffSSebastian Andrzej Siewior for (cpu = 0; cpu < cw->stream_cnt; cpu++) 118990e129ffSSebastian Andrzej Siewior ctf_stream__delete(cw->stream[cpu]); 119090e129ffSSebastian Andrzej Siewior 119190e129ffSSebastian Andrzej Siewior free(cw->stream); 119290e129ffSSebastian Andrzej Siewior } 119390e129ffSSebastian Andrzej Siewior 1194edbe9817SJiri Olsa static int ctf_writer__setup_env(struct ctf_writer *cw, 1195edbe9817SJiri Olsa struct perf_session *session) 1196edbe9817SJiri Olsa { 1197edbe9817SJiri Olsa struct perf_header *header = &session->header; 1198edbe9817SJiri Olsa struct bt_ctf_writer *writer = cw->writer; 1199edbe9817SJiri Olsa 1200edbe9817SJiri Olsa #define ADD(__n, __v) \ 1201edbe9817SJiri Olsa do { \ 1202edbe9817SJiri Olsa if (bt_ctf_writer_add_environment_field(writer, __n, __v)) \ 1203edbe9817SJiri Olsa return -1; \ 1204edbe9817SJiri Olsa } while (0) 1205edbe9817SJiri Olsa 1206edbe9817SJiri Olsa ADD("host", header->env.hostname); 1207edbe9817SJiri Olsa ADD("sysname", "Linux"); 1208edbe9817SJiri Olsa ADD("release", header->env.os_release); 1209edbe9817SJiri Olsa ADD("version", header->env.version); 1210edbe9817SJiri Olsa ADD("machine", header->env.arch); 1211edbe9817SJiri Olsa ADD("domain", "kernel"); 1212edbe9817SJiri Olsa ADD("tracer_name", "perf"); 1213edbe9817SJiri Olsa 1214edbe9817SJiri Olsa #undef ADD 1215edbe9817SJiri Olsa return 0; 1216edbe9817SJiri Olsa } 1217edbe9817SJiri Olsa 1218edbe9817SJiri Olsa static int ctf_writer__setup_clock(struct ctf_writer *cw) 1219edbe9817SJiri Olsa { 1220edbe9817SJiri Olsa struct bt_ctf_clock *clock = cw->clock; 1221edbe9817SJiri Olsa 1222edbe9817SJiri Olsa bt_ctf_clock_set_description(clock, "perf clock"); 1223edbe9817SJiri Olsa 1224edbe9817SJiri Olsa #define SET(__n, __v) \ 1225edbe9817SJiri Olsa do { \ 1226edbe9817SJiri Olsa if (bt_ctf_clock_set_##__n(clock, __v)) \ 1227edbe9817SJiri Olsa return -1; \ 1228edbe9817SJiri Olsa } while (0) 1229edbe9817SJiri Olsa 1230edbe9817SJiri Olsa SET(frequency, 1000000000); 1231edbe9817SJiri Olsa SET(offset_s, 0); 1232edbe9817SJiri Olsa SET(offset, 0); 1233edbe9817SJiri Olsa SET(precision, 10); 1234edbe9817SJiri Olsa SET(is_absolute, 0); 1235edbe9817SJiri Olsa 1236edbe9817SJiri Olsa #undef SET 1237edbe9817SJiri Olsa return 0; 1238edbe9817SJiri Olsa } 1239edbe9817SJiri Olsa 1240edbe9817SJiri Olsa static struct bt_ctf_field_type *create_int_type(int size, bool sign, bool hex) 1241edbe9817SJiri Olsa { 1242edbe9817SJiri Olsa struct bt_ctf_field_type *type; 1243edbe9817SJiri Olsa 1244edbe9817SJiri Olsa type = bt_ctf_field_type_integer_create(size); 1245edbe9817SJiri Olsa if (!type) 1246edbe9817SJiri Olsa return NULL; 1247edbe9817SJiri Olsa 1248edbe9817SJiri Olsa if (sign && 1249edbe9817SJiri Olsa bt_ctf_field_type_integer_set_signed(type, 1)) 1250edbe9817SJiri Olsa goto err; 1251edbe9817SJiri Olsa 1252edbe9817SJiri Olsa if (hex && 1253edbe9817SJiri Olsa bt_ctf_field_type_integer_set_base(type, BT_CTF_INTEGER_BASE_HEXADECIMAL)) 1254edbe9817SJiri Olsa goto err; 1255edbe9817SJiri Olsa 1256f8dd2d5fSWang Nan #if __BYTE_ORDER == __BIG_ENDIAN 1257f8dd2d5fSWang Nan bt_ctf_field_type_set_byte_order(type, BT_CTF_BYTE_ORDER_BIG_ENDIAN); 1258f8dd2d5fSWang Nan #else 1259f8dd2d5fSWang Nan bt_ctf_field_type_set_byte_order(type, BT_CTF_BYTE_ORDER_LITTLE_ENDIAN); 1260f8dd2d5fSWang Nan #endif 1261f8dd2d5fSWang Nan 1262edbe9817SJiri Olsa pr2("Created type: INTEGER %d-bit %ssigned %s\n", 1263edbe9817SJiri Olsa size, sign ? "un" : "", hex ? "hex" : ""); 1264edbe9817SJiri Olsa return type; 1265edbe9817SJiri Olsa 1266edbe9817SJiri Olsa err: 1267edbe9817SJiri Olsa bt_ctf_field_type_put(type); 1268edbe9817SJiri Olsa return NULL; 1269edbe9817SJiri Olsa } 1270edbe9817SJiri Olsa 1271edbe9817SJiri Olsa static void ctf_writer__cleanup_data(struct ctf_writer *cw) 1272edbe9817SJiri Olsa { 1273edbe9817SJiri Olsa unsigned int i; 1274edbe9817SJiri Olsa 1275edbe9817SJiri Olsa for (i = 0; i < ARRAY_SIZE(cw->data.array); i++) 1276edbe9817SJiri Olsa bt_ctf_field_type_put(cw->data.array[i]); 1277edbe9817SJiri Olsa } 1278edbe9817SJiri Olsa 1279edbe9817SJiri Olsa static int ctf_writer__init_data(struct ctf_writer *cw) 1280edbe9817SJiri Olsa { 1281edbe9817SJiri Olsa #define CREATE_INT_TYPE(type, size, sign, hex) \ 1282edbe9817SJiri Olsa do { \ 1283edbe9817SJiri Olsa (type) = create_int_type(size, sign, hex); \ 1284edbe9817SJiri Olsa if (!(type)) \ 1285edbe9817SJiri Olsa goto err; \ 1286edbe9817SJiri Olsa } while (0) 1287edbe9817SJiri Olsa 1288edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.s64, 64, true, false); 1289edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.u64, 64, false, false); 1290edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.s32, 32, true, false); 1291edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.u32, 32, false, false); 129226812d46SWang Nan CREATE_INT_TYPE(cw->data.u32_hex, 32, false, true); 1293edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true); 1294edbe9817SJiri Olsa 1295edbe9817SJiri Olsa cw->data.string = bt_ctf_field_type_string_create(); 1296edbe9817SJiri Olsa if (cw->data.string) 1297edbe9817SJiri Olsa return 0; 1298edbe9817SJiri Olsa 1299edbe9817SJiri Olsa err: 1300edbe9817SJiri Olsa ctf_writer__cleanup_data(cw); 1301edbe9817SJiri Olsa pr_err("Failed to create data types.\n"); 1302edbe9817SJiri Olsa return -1; 1303edbe9817SJiri Olsa } 1304edbe9817SJiri Olsa 1305edbe9817SJiri Olsa static void ctf_writer__cleanup(struct ctf_writer *cw) 1306edbe9817SJiri Olsa { 1307edbe9817SJiri Olsa ctf_writer__cleanup_data(cw); 1308edbe9817SJiri Olsa 1309edbe9817SJiri Olsa bt_ctf_clock_put(cw->clock); 131090e129ffSSebastian Andrzej Siewior free_streams(cw); 1311edbe9817SJiri Olsa bt_ctf_stream_class_put(cw->stream_class); 1312edbe9817SJiri Olsa bt_ctf_writer_put(cw->writer); 1313edbe9817SJiri Olsa 1314edbe9817SJiri Olsa /* and NULL all the pointers */ 1315edbe9817SJiri Olsa memset(cw, 0, sizeof(*cw)); 1316edbe9817SJiri Olsa } 1317edbe9817SJiri Olsa 1318edbe9817SJiri Olsa static int ctf_writer__init(struct ctf_writer *cw, const char *path) 1319edbe9817SJiri Olsa { 1320edbe9817SJiri Olsa struct bt_ctf_writer *writer; 1321edbe9817SJiri Olsa struct bt_ctf_stream_class *stream_class; 1322edbe9817SJiri Olsa struct bt_ctf_clock *clock; 132390e129ffSSebastian Andrzej Siewior struct bt_ctf_field_type *pkt_ctx_type; 132490e129ffSSebastian Andrzej Siewior int ret; 1325edbe9817SJiri Olsa 1326edbe9817SJiri Olsa /* CTF writer */ 1327edbe9817SJiri Olsa writer = bt_ctf_writer_create(path); 1328edbe9817SJiri Olsa if (!writer) 1329edbe9817SJiri Olsa goto err; 1330edbe9817SJiri Olsa 1331edbe9817SJiri Olsa cw->writer = writer; 1332edbe9817SJiri Olsa 1333edbe9817SJiri Olsa /* CTF clock */ 1334edbe9817SJiri Olsa clock = bt_ctf_clock_create("perf_clock"); 1335edbe9817SJiri Olsa if (!clock) { 1336edbe9817SJiri Olsa pr("Failed to create CTF clock.\n"); 1337edbe9817SJiri Olsa goto err_cleanup; 1338edbe9817SJiri Olsa } 1339edbe9817SJiri Olsa 1340edbe9817SJiri Olsa cw->clock = clock; 1341edbe9817SJiri Olsa 1342edbe9817SJiri Olsa if (ctf_writer__setup_clock(cw)) { 1343edbe9817SJiri Olsa pr("Failed to setup CTF clock.\n"); 1344edbe9817SJiri Olsa goto err_cleanup; 1345edbe9817SJiri Olsa } 1346edbe9817SJiri Olsa 1347edbe9817SJiri Olsa /* CTF stream class */ 1348edbe9817SJiri Olsa stream_class = bt_ctf_stream_class_create("perf_stream"); 1349edbe9817SJiri Olsa if (!stream_class) { 1350edbe9817SJiri Olsa pr("Failed to create CTF stream class.\n"); 1351edbe9817SJiri Olsa goto err_cleanup; 1352edbe9817SJiri Olsa } 1353edbe9817SJiri Olsa 1354edbe9817SJiri Olsa cw->stream_class = stream_class; 1355edbe9817SJiri Olsa 1356edbe9817SJiri Olsa /* CTF clock stream setup */ 1357edbe9817SJiri Olsa if (bt_ctf_stream_class_set_clock(stream_class, clock)) { 1358edbe9817SJiri Olsa pr("Failed to assign CTF clock to stream class.\n"); 1359edbe9817SJiri Olsa goto err_cleanup; 1360edbe9817SJiri Olsa } 1361edbe9817SJiri Olsa 1362edbe9817SJiri Olsa if (ctf_writer__init_data(cw)) 1363edbe9817SJiri Olsa goto err_cleanup; 1364edbe9817SJiri Olsa 136590e129ffSSebastian Andrzej Siewior /* Add cpu_id for packet context */ 136690e129ffSSebastian Andrzej Siewior pkt_ctx_type = bt_ctf_stream_class_get_packet_context_type(stream_class); 136790e129ffSSebastian Andrzej Siewior if (!pkt_ctx_type) 1368edbe9817SJiri Olsa goto err_cleanup; 1369edbe9817SJiri Olsa 137090e129ffSSebastian Andrzej Siewior ret = bt_ctf_field_type_structure_add_field(pkt_ctx_type, cw->data.u32, "cpu_id"); 137190e129ffSSebastian Andrzej Siewior bt_ctf_field_type_put(pkt_ctx_type); 137290e129ffSSebastian Andrzej Siewior if (ret) 137390e129ffSSebastian Andrzej Siewior goto err_cleanup; 1374edbe9817SJiri Olsa 1375edbe9817SJiri Olsa /* CTF clock writer setup */ 1376edbe9817SJiri Olsa if (bt_ctf_writer_add_clock(writer, clock)) { 1377edbe9817SJiri Olsa pr("Failed to assign CTF clock to writer.\n"); 1378edbe9817SJiri Olsa goto err_cleanup; 1379edbe9817SJiri Olsa } 1380edbe9817SJiri Olsa 1381edbe9817SJiri Olsa return 0; 1382edbe9817SJiri Olsa 1383edbe9817SJiri Olsa err_cleanup: 1384edbe9817SJiri Olsa ctf_writer__cleanup(cw); 1385edbe9817SJiri Olsa err: 1386edbe9817SJiri Olsa pr_err("Failed to setup CTF writer.\n"); 1387edbe9817SJiri Olsa return -1; 1388edbe9817SJiri Olsa } 1389edbe9817SJiri Olsa 139090e129ffSSebastian Andrzej Siewior static int ctf_writer__flush_streams(struct ctf_writer *cw) 139190e129ffSSebastian Andrzej Siewior { 139290e129ffSSebastian Andrzej Siewior int cpu, ret = 0; 139390e129ffSSebastian Andrzej Siewior 139490e129ffSSebastian Andrzej Siewior for (cpu = 0; cpu < cw->stream_cnt && !ret; cpu++) 139590e129ffSSebastian Andrzej Siewior ret = ctf_stream__flush(cw->stream[cpu]); 139690e129ffSSebastian Andrzej Siewior 139790e129ffSSebastian Andrzej Siewior return ret; 139890e129ffSSebastian Andrzej Siewior } 139990e129ffSSebastian Andrzej Siewior 14008fa46753SJiri Olsa static int convert__config(const char *var, const char *value, void *cb) 14018fa46753SJiri Olsa { 14028fa46753SJiri Olsa struct convert *c = cb; 14038fa46753SJiri Olsa 14048fa46753SJiri Olsa if (!strcmp(var, "convert.queue-size")) { 14058fa46753SJiri Olsa c->queue_size = perf_config_u64(var, value); 14068fa46753SJiri Olsa return 0; 14078fa46753SJiri Olsa } 14088fa46753SJiri Olsa 1409b8cbb349SWang Nan return 0; 14108fa46753SJiri Olsa } 14118fa46753SJiri Olsa 14123275f68eSWang Nan int bt_convert__perf2ctf(const char *input, const char *path, 14133275f68eSWang Nan struct perf_data_convert_opts *opts) 1414edbe9817SJiri Olsa { 1415edbe9817SJiri Olsa struct perf_session *session; 1416edbe9817SJiri Olsa struct perf_data_file file = { 1417edbe9817SJiri Olsa .path = input, 1418edbe9817SJiri Olsa .mode = PERF_DATA_MODE_READ, 14193275f68eSWang Nan .force = opts->force, 1420edbe9817SJiri Olsa }; 1421edbe9817SJiri Olsa struct convert c = { 1422edbe9817SJiri Olsa .tool = { 1423edbe9817SJiri Olsa .sample = process_sample_event, 1424edbe9817SJiri Olsa .mmap = perf_event__process_mmap, 1425edbe9817SJiri Olsa .mmap2 = perf_event__process_mmap2, 1426edbe9817SJiri Olsa .comm = perf_event__process_comm, 1427edbe9817SJiri Olsa .exit = perf_event__process_exit, 1428edbe9817SJiri Olsa .fork = perf_event__process_fork, 1429edbe9817SJiri Olsa .lost = perf_event__process_lost, 1430edbe9817SJiri Olsa .tracing_data = perf_event__process_tracing_data, 1431edbe9817SJiri Olsa .build_id = perf_event__process_build_id, 1432edbe9817SJiri Olsa .ordered_events = true, 1433edbe9817SJiri Olsa .ordering_requires_timestamps = true, 1434edbe9817SJiri Olsa }, 1435edbe9817SJiri Olsa }; 1436edbe9817SJiri Olsa struct ctf_writer *cw = &c.writer; 1437edbe9817SJiri Olsa int err = -1; 1438edbe9817SJiri Olsa 1439*f5a08cedSWang Nan if (opts->all) 1440*f5a08cedSWang Nan c.tool.comm = process_comm_event; 1441*f5a08cedSWang Nan 14428fa46753SJiri Olsa perf_config(convert__config, &c); 14438fa46753SJiri Olsa 1444edbe9817SJiri Olsa /* CTF writer */ 1445edbe9817SJiri Olsa if (ctf_writer__init(cw, path)) 1446edbe9817SJiri Olsa return -1; 1447edbe9817SJiri Olsa 1448edbe9817SJiri Olsa /* perf.data session */ 1449b7b61cbeSArnaldo Carvalho de Melo session = perf_session__new(&file, 0, &c.tool); 1450edbe9817SJiri Olsa if (!session) 1451edbe9817SJiri Olsa goto free_writer; 1452edbe9817SJiri Olsa 14538fa46753SJiri Olsa if (c.queue_size) { 14548fa46753SJiri Olsa ordered_events__set_alloc_size(&session->ordered_events, 14558fa46753SJiri Olsa c.queue_size); 14568fa46753SJiri Olsa } 14578fa46753SJiri Olsa 1458edbe9817SJiri Olsa /* CTF writer env/clock setup */ 1459edbe9817SJiri Olsa if (ctf_writer__setup_env(cw, session)) 1460edbe9817SJiri Olsa goto free_session; 1461edbe9817SJiri Olsa 1462edbe9817SJiri Olsa /* CTF events setup */ 1463edbe9817SJiri Olsa if (setup_events(cw, session)) 1464edbe9817SJiri Olsa goto free_session; 1465edbe9817SJiri Olsa 1466*f5a08cedSWang Nan if (opts->all && setup_non_sample_events(cw, session)) 1467*f5a08cedSWang Nan goto free_session; 1468*f5a08cedSWang Nan 146990e129ffSSebastian Andrzej Siewior if (setup_streams(cw, session)) 147090e129ffSSebastian Andrzej Siewior goto free_session; 147190e129ffSSebastian Andrzej Siewior 1472b7b61cbeSArnaldo Carvalho de Melo err = perf_session__process_events(session); 1473edbe9817SJiri Olsa if (!err) 147490e129ffSSebastian Andrzej Siewior err = ctf_writer__flush_streams(cw); 1475c2141055SHe Kuang else 1476c2141055SHe Kuang pr_err("Error during conversion.\n"); 1477edbe9817SJiri Olsa 1478edbe9817SJiri Olsa fprintf(stderr, 1479edbe9817SJiri Olsa "[ perf data convert: Converted '%s' into CTF data '%s' ]\n", 1480edbe9817SJiri Olsa file.path, path); 1481edbe9817SJiri Olsa 1482edbe9817SJiri Olsa fprintf(stderr, 14838ee4c46cSWang Nan "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples", 1484edbe9817SJiri Olsa (double) c.events_size / 1024.0 / 1024.0, 1485edbe9817SJiri Olsa c.events_count); 1486edbe9817SJiri Olsa 14878ee4c46cSWang Nan if (!c.non_sample_count) 14888ee4c46cSWang Nan fprintf(stderr, ") ]\n"); 14898ee4c46cSWang Nan else 14908ee4c46cSWang Nan fprintf(stderr, ", %" PRIu64 " non-samples) ]\n", c.non_sample_count); 14918ee4c46cSWang Nan 14925141d735SWang Nan cleanup_events(session); 1493c2141055SHe Kuang perf_session__delete(session); 1494c2141055SHe Kuang ctf_writer__cleanup(cw); 1495c2141055SHe Kuang 1496c2141055SHe Kuang return err; 1497c2141055SHe Kuang 1498edbe9817SJiri Olsa free_session: 1499edbe9817SJiri Olsa perf_session__delete(session); 1500edbe9817SJiri Olsa free_writer: 1501edbe9817SJiri Olsa ctf_writer__cleanup(cw); 1502c2141055SHe Kuang pr_err("Error during conversion setup.\n"); 1503edbe9817SJiri Olsa return err; 1504edbe9817SJiri Olsa } 1505