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