1 /* 2 * CTF writing support via babeltrace. 3 * 4 * Copyright (C) 2014, Jiri Olsa <jolsa@redhat.com> 5 * Copyright (C) 2014, Sebastian Andrzej Siewior <bigeasy@linutronix.de> 6 * 7 * Released under the GPL v2. (and only v2, not any later version) 8 */ 9 10 #include <linux/compiler.h> 11 #include <babeltrace/ctf-writer/writer.h> 12 #include <babeltrace/ctf-writer/clock.h> 13 #include <babeltrace/ctf-writer/stream.h> 14 #include <babeltrace/ctf-writer/event.h> 15 #include <babeltrace/ctf-writer/event-types.h> 16 #include <babeltrace/ctf-writer/event-fields.h> 17 #include <babeltrace/ctf-ir/utils.h> 18 #include <babeltrace/ctf/events.h> 19 #include <traceevent/event-parse.h> 20 #include "asm/bug.h" 21 #include "data-convert-bt.h" 22 #include "session.h" 23 #include "util.h" 24 #include "debug.h" 25 #include "tool.h" 26 #include "evlist.h" 27 #include "evsel.h" 28 #include "machine.h" 29 30 #define pr_N(n, fmt, ...) \ 31 eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__) 32 33 #define pr(fmt, ...) pr_N(1, pr_fmt(fmt), ##__VA_ARGS__) 34 #define pr2(fmt, ...) pr_N(2, pr_fmt(fmt), ##__VA_ARGS__) 35 36 #define pr_time2(t, fmt, ...) pr_time_N(2, debug_data_convert, t, pr_fmt(fmt), ##__VA_ARGS__) 37 38 struct evsel_priv { 39 struct bt_ctf_event_class *event_class; 40 }; 41 42 #define MAX_CPUS 4096 43 44 struct ctf_stream { 45 struct bt_ctf_stream *stream; 46 int cpu; 47 u32 count; 48 }; 49 50 struct ctf_writer { 51 /* writer primitives */ 52 struct bt_ctf_writer *writer; 53 struct ctf_stream **stream; 54 int stream_cnt; 55 struct bt_ctf_stream_class *stream_class; 56 struct bt_ctf_clock *clock; 57 58 /* data types */ 59 union { 60 struct { 61 struct bt_ctf_field_type *s64; 62 struct bt_ctf_field_type *u64; 63 struct bt_ctf_field_type *s32; 64 struct bt_ctf_field_type *u32; 65 struct bt_ctf_field_type *string; 66 struct bt_ctf_field_type *u32_hex; 67 struct bt_ctf_field_type *u64_hex; 68 }; 69 struct bt_ctf_field_type *array[6]; 70 } data; 71 }; 72 73 struct convert { 74 struct perf_tool tool; 75 struct ctf_writer writer; 76 77 u64 events_size; 78 u64 events_count; 79 80 /* Ordered events configured queue size. */ 81 u64 queue_size; 82 }; 83 84 static int value_set(struct bt_ctf_field_type *type, 85 struct bt_ctf_event *event, 86 const char *name, u64 val) 87 { 88 struct bt_ctf_field *field; 89 bool sign = bt_ctf_field_type_integer_get_signed(type); 90 int ret; 91 92 field = bt_ctf_field_create(type); 93 if (!field) { 94 pr_err("failed to create a field %s\n", name); 95 return -1; 96 } 97 98 if (sign) { 99 ret = bt_ctf_field_signed_integer_set_value(field, val); 100 if (ret) { 101 pr_err("failed to set field value %s\n", name); 102 goto err; 103 } 104 } else { 105 ret = bt_ctf_field_unsigned_integer_set_value(field, val); 106 if (ret) { 107 pr_err("failed to set field value %s\n", name); 108 goto err; 109 } 110 } 111 112 ret = bt_ctf_event_set_payload(event, name, field); 113 if (ret) { 114 pr_err("failed to set payload %s\n", name); 115 goto err; 116 } 117 118 pr2(" SET [%s = %" PRIu64 "]\n", name, val); 119 120 err: 121 bt_ctf_field_put(field); 122 return ret; 123 } 124 125 #define __FUNC_VALUE_SET(_name, _val_type) \ 126 static __maybe_unused int value_set_##_name(struct ctf_writer *cw, \ 127 struct bt_ctf_event *event, \ 128 const char *name, \ 129 _val_type val) \ 130 { \ 131 struct bt_ctf_field_type *type = cw->data._name; \ 132 return value_set(type, event, name, (u64) val); \ 133 } 134 135 #define FUNC_VALUE_SET(_name) __FUNC_VALUE_SET(_name, _name) 136 137 FUNC_VALUE_SET(s32) 138 FUNC_VALUE_SET(u32) 139 FUNC_VALUE_SET(s64) 140 FUNC_VALUE_SET(u64) 141 __FUNC_VALUE_SET(u64_hex, u64) 142 143 static struct bt_ctf_field_type* 144 get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field) 145 { 146 unsigned long flags = field->flags; 147 148 if (flags & FIELD_IS_STRING) 149 return cw->data.string; 150 151 if (!(flags & FIELD_IS_SIGNED)) { 152 /* unsigned long are mostly pointers */ 153 if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER) 154 return cw->data.u64_hex; 155 } 156 157 if (flags & FIELD_IS_SIGNED) { 158 if (field->size == 8) 159 return cw->data.s64; 160 else 161 return cw->data.s32; 162 } 163 164 if (field->size == 8) 165 return cw->data.u64; 166 else 167 return cw->data.u32; 168 } 169 170 static unsigned long long adjust_signedness(unsigned long long value_int, int size) 171 { 172 unsigned long long value_mask; 173 174 /* 175 * value_mask = (1 << (size * 8 - 1)) - 1. 176 * Directly set value_mask for code readers. 177 */ 178 switch (size) { 179 case 1: 180 value_mask = 0x7fULL; 181 break; 182 case 2: 183 value_mask = 0x7fffULL; 184 break; 185 case 4: 186 value_mask = 0x7fffffffULL; 187 break; 188 case 8: 189 /* 190 * For 64 bit value, return it self. There is no need 191 * to fill high bit. 192 */ 193 /* Fall through */ 194 default: 195 /* BUG! */ 196 return value_int; 197 } 198 199 /* If it is a positive value, don't adjust. */ 200 if ((value_int & (~0ULL - value_mask)) == 0) 201 return value_int; 202 203 /* Fill upper part of value_int with 1 to make it a negative long long. */ 204 return (value_int & value_mask) | ~value_mask; 205 } 206 207 static int add_tracepoint_field_value(struct ctf_writer *cw, 208 struct bt_ctf_event_class *event_class, 209 struct bt_ctf_event *event, 210 struct perf_sample *sample, 211 struct format_field *fmtf) 212 { 213 struct bt_ctf_field_type *type; 214 struct bt_ctf_field *array_field; 215 struct bt_ctf_field *field; 216 const char *name = fmtf->name; 217 void *data = sample->raw_data; 218 unsigned long flags = fmtf->flags; 219 unsigned int n_items; 220 unsigned int i; 221 unsigned int offset; 222 unsigned int len; 223 int ret; 224 225 name = fmtf->alias; 226 offset = fmtf->offset; 227 len = fmtf->size; 228 if (flags & FIELD_IS_STRING) 229 flags &= ~FIELD_IS_ARRAY; 230 231 if (flags & FIELD_IS_DYNAMIC) { 232 unsigned long long tmp_val; 233 234 tmp_val = pevent_read_number(fmtf->event->pevent, 235 data + offset, len); 236 offset = tmp_val; 237 len = offset >> 16; 238 offset &= 0xffff; 239 } 240 241 if (flags & FIELD_IS_ARRAY) { 242 243 type = bt_ctf_event_class_get_field_by_name( 244 event_class, name); 245 array_field = bt_ctf_field_create(type); 246 bt_ctf_field_type_put(type); 247 if (!array_field) { 248 pr_err("Failed to create array type %s\n", name); 249 return -1; 250 } 251 252 len = fmtf->size / fmtf->arraylen; 253 n_items = fmtf->arraylen; 254 } else { 255 n_items = 1; 256 array_field = NULL; 257 } 258 259 type = get_tracepoint_field_type(cw, fmtf); 260 261 for (i = 0; i < n_items; i++) { 262 if (flags & FIELD_IS_ARRAY) 263 field = bt_ctf_field_array_get_field(array_field, i); 264 else 265 field = bt_ctf_field_create(type); 266 267 if (!field) { 268 pr_err("failed to create a field %s\n", name); 269 return -1; 270 } 271 272 if (flags & FIELD_IS_STRING) 273 ret = bt_ctf_field_string_set_value(field, 274 data + offset + i * len); 275 else { 276 unsigned long long value_int; 277 278 value_int = pevent_read_number( 279 fmtf->event->pevent, 280 data + offset + i * len, len); 281 282 if (!(flags & FIELD_IS_SIGNED)) 283 ret = bt_ctf_field_unsigned_integer_set_value( 284 field, value_int); 285 else 286 ret = bt_ctf_field_signed_integer_set_value( 287 field, adjust_signedness(value_int, len)); 288 } 289 290 if (ret) { 291 pr_err("failed to set file value %s\n", name); 292 goto err_put_field; 293 } 294 if (!(flags & FIELD_IS_ARRAY)) { 295 ret = bt_ctf_event_set_payload(event, name, field); 296 if (ret) { 297 pr_err("failed to set payload %s\n", name); 298 goto err_put_field; 299 } 300 } 301 bt_ctf_field_put(field); 302 } 303 if (flags & FIELD_IS_ARRAY) { 304 ret = bt_ctf_event_set_payload(event, name, array_field); 305 if (ret) { 306 pr_err("Failed add payload array %s\n", name); 307 return -1; 308 } 309 bt_ctf_field_put(array_field); 310 } 311 return 0; 312 313 err_put_field: 314 bt_ctf_field_put(field); 315 return -1; 316 } 317 318 static int add_tracepoint_fields_values(struct ctf_writer *cw, 319 struct bt_ctf_event_class *event_class, 320 struct bt_ctf_event *event, 321 struct format_field *fields, 322 struct perf_sample *sample) 323 { 324 struct format_field *field; 325 int ret; 326 327 for (field = fields; field; field = field->next) { 328 ret = add_tracepoint_field_value(cw, event_class, event, sample, 329 field); 330 if (ret) 331 return -1; 332 } 333 return 0; 334 } 335 336 static int add_tracepoint_values(struct ctf_writer *cw, 337 struct bt_ctf_event_class *event_class, 338 struct bt_ctf_event *event, 339 struct perf_evsel *evsel, 340 struct perf_sample *sample) 341 { 342 struct format_field *common_fields = evsel->tp_format->format.common_fields; 343 struct format_field *fields = evsel->tp_format->format.fields; 344 int ret; 345 346 ret = add_tracepoint_fields_values(cw, event_class, event, 347 common_fields, sample); 348 if (!ret) 349 ret = add_tracepoint_fields_values(cw, event_class, event, 350 fields, sample); 351 352 return ret; 353 } 354 355 static int add_generic_values(struct ctf_writer *cw, 356 struct bt_ctf_event *event, 357 struct perf_evsel *evsel, 358 struct perf_sample *sample) 359 { 360 u64 type = evsel->attr.sample_type; 361 int ret; 362 363 /* 364 * missing: 365 * PERF_SAMPLE_TIME - not needed as we have it in 366 * ctf event header 367 * PERF_SAMPLE_READ - TODO 368 * PERF_SAMPLE_CALLCHAIN - TODO 369 * PERF_SAMPLE_RAW - tracepoint fields are handled separately 370 * PERF_SAMPLE_BRANCH_STACK - TODO 371 * PERF_SAMPLE_REGS_USER - TODO 372 * PERF_SAMPLE_STACK_USER - TODO 373 */ 374 375 if (type & PERF_SAMPLE_IP) { 376 ret = value_set_u64_hex(cw, event, "perf_ip", sample->ip); 377 if (ret) 378 return -1; 379 } 380 381 if (type & PERF_SAMPLE_TID) { 382 ret = value_set_s32(cw, event, "perf_tid", sample->tid); 383 if (ret) 384 return -1; 385 386 ret = value_set_s32(cw, event, "perf_pid", sample->pid); 387 if (ret) 388 return -1; 389 } 390 391 if ((type & PERF_SAMPLE_ID) || 392 (type & PERF_SAMPLE_IDENTIFIER)) { 393 ret = value_set_u64(cw, event, "perf_id", sample->id); 394 if (ret) 395 return -1; 396 } 397 398 if (type & PERF_SAMPLE_STREAM_ID) { 399 ret = value_set_u64(cw, event, "perf_stream_id", sample->stream_id); 400 if (ret) 401 return -1; 402 } 403 404 if (type & PERF_SAMPLE_PERIOD) { 405 ret = value_set_u64(cw, event, "perf_period", sample->period); 406 if (ret) 407 return -1; 408 } 409 410 if (type & PERF_SAMPLE_WEIGHT) { 411 ret = value_set_u64(cw, event, "perf_weight", sample->weight); 412 if (ret) 413 return -1; 414 } 415 416 if (type & PERF_SAMPLE_DATA_SRC) { 417 ret = value_set_u64(cw, event, "perf_data_src", 418 sample->data_src); 419 if (ret) 420 return -1; 421 } 422 423 if (type & PERF_SAMPLE_TRANSACTION) { 424 ret = value_set_u64(cw, event, "perf_transaction", 425 sample->transaction); 426 if (ret) 427 return -1; 428 } 429 430 return 0; 431 } 432 433 static int ctf_stream__flush(struct ctf_stream *cs) 434 { 435 int err = 0; 436 437 if (cs) { 438 err = bt_ctf_stream_flush(cs->stream); 439 if (err) 440 pr_err("CTF stream %d flush failed\n", cs->cpu); 441 442 pr("Flush stream for cpu %d (%u samples)\n", 443 cs->cpu, cs->count); 444 445 cs->count = 0; 446 } 447 448 return err; 449 } 450 451 static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu) 452 { 453 struct ctf_stream *cs; 454 struct bt_ctf_field *pkt_ctx = NULL; 455 struct bt_ctf_field *cpu_field = NULL; 456 struct bt_ctf_stream *stream = NULL; 457 int ret; 458 459 cs = zalloc(sizeof(*cs)); 460 if (!cs) { 461 pr_err("Failed to allocate ctf stream\n"); 462 return NULL; 463 } 464 465 stream = bt_ctf_writer_create_stream(cw->writer, cw->stream_class); 466 if (!stream) { 467 pr_err("Failed to create CTF stream\n"); 468 goto out; 469 } 470 471 pkt_ctx = bt_ctf_stream_get_packet_context(stream); 472 if (!pkt_ctx) { 473 pr_err("Failed to obtain packet context\n"); 474 goto out; 475 } 476 477 cpu_field = bt_ctf_field_structure_get_field(pkt_ctx, "cpu_id"); 478 bt_ctf_field_put(pkt_ctx); 479 if (!cpu_field) { 480 pr_err("Failed to obtain cpu field\n"); 481 goto out; 482 } 483 484 ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu); 485 if (ret) { 486 pr_err("Failed to update CPU number\n"); 487 goto out; 488 } 489 490 bt_ctf_field_put(cpu_field); 491 492 cs->cpu = cpu; 493 cs->stream = stream; 494 return cs; 495 496 out: 497 if (cpu_field) 498 bt_ctf_field_put(cpu_field); 499 if (stream) 500 bt_ctf_stream_put(stream); 501 502 free(cs); 503 return NULL; 504 } 505 506 static void ctf_stream__delete(struct ctf_stream *cs) 507 { 508 if (cs) { 509 bt_ctf_stream_put(cs->stream); 510 free(cs); 511 } 512 } 513 514 static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu) 515 { 516 struct ctf_stream *cs = cw->stream[cpu]; 517 518 if (!cs) { 519 cs = ctf_stream__create(cw, cpu); 520 cw->stream[cpu] = cs; 521 } 522 523 return cs; 524 } 525 526 static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample, 527 struct perf_evsel *evsel) 528 { 529 int cpu = 0; 530 531 if (evsel->attr.sample_type & PERF_SAMPLE_CPU) 532 cpu = sample->cpu; 533 534 if (cpu > cw->stream_cnt) { 535 pr_err("Event was recorded for CPU %d, limit is at %d.\n", 536 cpu, cw->stream_cnt); 537 cpu = 0; 538 } 539 540 return cpu; 541 } 542 543 #define STREAM_FLUSH_COUNT 100000 544 545 /* 546 * Currently we have no other way to determine the 547 * time for the stream flush other than keep track 548 * of the number of events and check it against 549 * threshold. 550 */ 551 static bool is_flush_needed(struct ctf_stream *cs) 552 { 553 return cs->count >= STREAM_FLUSH_COUNT; 554 } 555 556 static int process_sample_event(struct perf_tool *tool, 557 union perf_event *_event __maybe_unused, 558 struct perf_sample *sample, 559 struct perf_evsel *evsel, 560 struct machine *machine __maybe_unused) 561 { 562 struct convert *c = container_of(tool, struct convert, tool); 563 struct evsel_priv *priv = evsel->priv; 564 struct ctf_writer *cw = &c->writer; 565 struct ctf_stream *cs; 566 struct bt_ctf_event_class *event_class; 567 struct bt_ctf_event *event; 568 int ret; 569 570 if (WARN_ONCE(!priv, "Failed to setup all events.\n")) 571 return 0; 572 573 event_class = priv->event_class; 574 575 /* update stats */ 576 c->events_count++; 577 c->events_size += _event->header.size; 578 579 pr_time2(sample->time, "sample %" PRIu64 "\n", c->events_count); 580 581 event = bt_ctf_event_create(event_class); 582 if (!event) { 583 pr_err("Failed to create an CTF event\n"); 584 return -1; 585 } 586 587 bt_ctf_clock_set_time(cw->clock, sample->time); 588 589 ret = add_generic_values(cw, event, evsel, sample); 590 if (ret) 591 return -1; 592 593 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) { 594 ret = add_tracepoint_values(cw, event_class, event, 595 evsel, sample); 596 if (ret) 597 return -1; 598 } 599 600 cs = ctf_stream(cw, get_sample_cpu(cw, sample, evsel)); 601 if (cs) { 602 if (is_flush_needed(cs)) 603 ctf_stream__flush(cs); 604 605 cs->count++; 606 bt_ctf_stream_append_event(cs->stream, event); 607 } 608 609 bt_ctf_event_put(event); 610 return cs ? 0 : -1; 611 } 612 613 /* If dup < 0, add a prefix. Else, add _dupl_X suffix. */ 614 static char *change_name(char *name, char *orig_name, int dup) 615 { 616 char *new_name = NULL; 617 size_t len; 618 619 if (!name) 620 name = orig_name; 621 622 if (dup >= 10) 623 goto out; 624 /* 625 * Add '_' prefix to potential keywork. According to 626 * Mathieu Desnoyers (https://lkml.org/lkml/2015/1/23/652), 627 * futher CTF spec updating may require us to use '$'. 628 */ 629 if (dup < 0) 630 len = strlen(name) + sizeof("_"); 631 else 632 len = strlen(orig_name) + sizeof("_dupl_X"); 633 634 new_name = malloc(len); 635 if (!new_name) 636 goto out; 637 638 if (dup < 0) 639 snprintf(new_name, len, "_%s", name); 640 else 641 snprintf(new_name, len, "%s_dupl_%d", orig_name, dup); 642 643 out: 644 if (name != orig_name) 645 free(name); 646 return new_name; 647 } 648 649 static int event_class_add_field(struct bt_ctf_event_class *event_class, 650 struct bt_ctf_field_type *type, 651 struct format_field *field) 652 { 653 struct bt_ctf_field_type *t = NULL; 654 char *name; 655 int dup = 1; 656 int ret; 657 658 /* alias was already assigned */ 659 if (field->alias != field->name) 660 return bt_ctf_event_class_add_field(event_class, type, 661 (char *)field->alias); 662 663 name = field->name; 664 665 /* If 'name' is a keywork, add prefix. */ 666 if (bt_ctf_validate_identifier(name)) 667 name = change_name(name, field->name, -1); 668 669 if (!name) { 670 pr_err("Failed to fix invalid identifier."); 671 return -1; 672 } 673 while ((t = bt_ctf_event_class_get_field_by_name(event_class, name))) { 674 bt_ctf_field_type_put(t); 675 name = change_name(name, field->name, dup++); 676 if (!name) { 677 pr_err("Failed to create dup name for '%s'\n", field->name); 678 return -1; 679 } 680 } 681 682 ret = bt_ctf_event_class_add_field(event_class, type, name); 683 if (!ret) 684 field->alias = name; 685 686 return ret; 687 } 688 689 static int add_tracepoint_fields_types(struct ctf_writer *cw, 690 struct format_field *fields, 691 struct bt_ctf_event_class *event_class) 692 { 693 struct format_field *field; 694 int ret; 695 696 for (field = fields; field; field = field->next) { 697 struct bt_ctf_field_type *type; 698 unsigned long flags = field->flags; 699 700 pr2(" field '%s'\n", field->name); 701 702 type = get_tracepoint_field_type(cw, field); 703 if (!type) 704 return -1; 705 706 /* 707 * A string is an array of chars. For this we use the string 708 * type and don't care that it is an array. What we don't 709 * support is an array of strings. 710 */ 711 if (flags & FIELD_IS_STRING) 712 flags &= ~FIELD_IS_ARRAY; 713 714 if (flags & FIELD_IS_ARRAY) 715 type = bt_ctf_field_type_array_create(type, field->arraylen); 716 717 ret = event_class_add_field(event_class, type, field); 718 719 if (flags & FIELD_IS_ARRAY) 720 bt_ctf_field_type_put(type); 721 722 if (ret) { 723 pr_err("Failed to add field '%s': %d\n", 724 field->name, ret); 725 return -1; 726 } 727 } 728 729 return 0; 730 } 731 732 static int add_tracepoint_types(struct ctf_writer *cw, 733 struct perf_evsel *evsel, 734 struct bt_ctf_event_class *class) 735 { 736 struct format_field *common_fields = evsel->tp_format->format.common_fields; 737 struct format_field *fields = evsel->tp_format->format.fields; 738 int ret; 739 740 ret = add_tracepoint_fields_types(cw, common_fields, class); 741 if (!ret) 742 ret = add_tracepoint_fields_types(cw, fields, class); 743 744 return ret; 745 } 746 747 static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel, 748 struct bt_ctf_event_class *event_class) 749 { 750 u64 type = evsel->attr.sample_type; 751 752 /* 753 * missing: 754 * PERF_SAMPLE_TIME - not needed as we have it in 755 * ctf event header 756 * PERF_SAMPLE_READ - TODO 757 * PERF_SAMPLE_CALLCHAIN - TODO 758 * PERF_SAMPLE_RAW - tracepoint fields are handled separately 759 * PERF_SAMPLE_BRANCH_STACK - TODO 760 * PERF_SAMPLE_REGS_USER - TODO 761 * PERF_SAMPLE_STACK_USER - TODO 762 */ 763 764 #define ADD_FIELD(cl, t, n) \ 765 do { \ 766 pr2(" field '%s'\n", n); \ 767 if (bt_ctf_event_class_add_field(cl, t, n)) { \ 768 pr_err("Failed to add field '%s';\n", n); \ 769 return -1; \ 770 } \ 771 } while (0) 772 773 if (type & PERF_SAMPLE_IP) 774 ADD_FIELD(event_class, cw->data.u64_hex, "perf_ip"); 775 776 if (type & PERF_SAMPLE_TID) { 777 ADD_FIELD(event_class, cw->data.s32, "perf_tid"); 778 ADD_FIELD(event_class, cw->data.s32, "perf_pid"); 779 } 780 781 if ((type & PERF_SAMPLE_ID) || 782 (type & PERF_SAMPLE_IDENTIFIER)) 783 ADD_FIELD(event_class, cw->data.u64, "perf_id"); 784 785 if (type & PERF_SAMPLE_STREAM_ID) 786 ADD_FIELD(event_class, cw->data.u64, "perf_stream_id"); 787 788 if (type & PERF_SAMPLE_PERIOD) 789 ADD_FIELD(event_class, cw->data.u64, "perf_period"); 790 791 if (type & PERF_SAMPLE_WEIGHT) 792 ADD_FIELD(event_class, cw->data.u64, "perf_weight"); 793 794 if (type & PERF_SAMPLE_DATA_SRC) 795 ADD_FIELD(event_class, cw->data.u64, "perf_data_src"); 796 797 if (type & PERF_SAMPLE_TRANSACTION) 798 ADD_FIELD(event_class, cw->data.u64, "perf_transaction"); 799 800 #undef ADD_FIELD 801 return 0; 802 } 803 804 static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel) 805 { 806 struct bt_ctf_event_class *event_class; 807 struct evsel_priv *priv; 808 const char *name = perf_evsel__name(evsel); 809 int ret; 810 811 pr("Adding event '%s' (type %d)\n", name, evsel->attr.type); 812 813 event_class = bt_ctf_event_class_create(name); 814 if (!event_class) 815 return -1; 816 817 ret = add_generic_types(cw, evsel, event_class); 818 if (ret) 819 goto err; 820 821 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) { 822 ret = add_tracepoint_types(cw, evsel, event_class); 823 if (ret) 824 goto err; 825 } 826 827 ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class); 828 if (ret) { 829 pr("Failed to add event class into stream.\n"); 830 goto err; 831 } 832 833 priv = malloc(sizeof(*priv)); 834 if (!priv) 835 goto err; 836 837 priv->event_class = event_class; 838 evsel->priv = priv; 839 return 0; 840 841 err: 842 bt_ctf_event_class_put(event_class); 843 pr_err("Failed to add event '%s'.\n", name); 844 return -1; 845 } 846 847 static int setup_events(struct ctf_writer *cw, struct perf_session *session) 848 { 849 struct perf_evlist *evlist = session->evlist; 850 struct perf_evsel *evsel; 851 int ret; 852 853 evlist__for_each(evlist, evsel) { 854 ret = add_event(cw, evsel); 855 if (ret) 856 return ret; 857 } 858 return 0; 859 } 860 861 static int setup_streams(struct ctf_writer *cw, struct perf_session *session) 862 { 863 struct ctf_stream **stream; 864 struct perf_header *ph = &session->header; 865 int ncpus; 866 867 /* 868 * Try to get the number of cpus used in the data file, 869 * if not present fallback to the MAX_CPUS. 870 */ 871 ncpus = ph->env.nr_cpus_avail ?: MAX_CPUS; 872 873 stream = zalloc(sizeof(*stream) * ncpus); 874 if (!stream) { 875 pr_err("Failed to allocate streams.\n"); 876 return -ENOMEM; 877 } 878 879 cw->stream = stream; 880 cw->stream_cnt = ncpus; 881 return 0; 882 } 883 884 static void free_streams(struct ctf_writer *cw) 885 { 886 int cpu; 887 888 for (cpu = 0; cpu < cw->stream_cnt; cpu++) 889 ctf_stream__delete(cw->stream[cpu]); 890 891 free(cw->stream); 892 } 893 894 static int ctf_writer__setup_env(struct ctf_writer *cw, 895 struct perf_session *session) 896 { 897 struct perf_header *header = &session->header; 898 struct bt_ctf_writer *writer = cw->writer; 899 900 #define ADD(__n, __v) \ 901 do { \ 902 if (bt_ctf_writer_add_environment_field(writer, __n, __v)) \ 903 return -1; \ 904 } while (0) 905 906 ADD("host", header->env.hostname); 907 ADD("sysname", "Linux"); 908 ADD("release", header->env.os_release); 909 ADD("version", header->env.version); 910 ADD("machine", header->env.arch); 911 ADD("domain", "kernel"); 912 ADD("tracer_name", "perf"); 913 914 #undef ADD 915 return 0; 916 } 917 918 static int ctf_writer__setup_clock(struct ctf_writer *cw) 919 { 920 struct bt_ctf_clock *clock = cw->clock; 921 922 bt_ctf_clock_set_description(clock, "perf clock"); 923 924 #define SET(__n, __v) \ 925 do { \ 926 if (bt_ctf_clock_set_##__n(clock, __v)) \ 927 return -1; \ 928 } while (0) 929 930 SET(frequency, 1000000000); 931 SET(offset_s, 0); 932 SET(offset, 0); 933 SET(precision, 10); 934 SET(is_absolute, 0); 935 936 #undef SET 937 return 0; 938 } 939 940 static struct bt_ctf_field_type *create_int_type(int size, bool sign, bool hex) 941 { 942 struct bt_ctf_field_type *type; 943 944 type = bt_ctf_field_type_integer_create(size); 945 if (!type) 946 return NULL; 947 948 if (sign && 949 bt_ctf_field_type_integer_set_signed(type, 1)) 950 goto err; 951 952 if (hex && 953 bt_ctf_field_type_integer_set_base(type, BT_CTF_INTEGER_BASE_HEXADECIMAL)) 954 goto err; 955 956 pr2("Created type: INTEGER %d-bit %ssigned %s\n", 957 size, sign ? "un" : "", hex ? "hex" : ""); 958 return type; 959 960 err: 961 bt_ctf_field_type_put(type); 962 return NULL; 963 } 964 965 static void ctf_writer__cleanup_data(struct ctf_writer *cw) 966 { 967 unsigned int i; 968 969 for (i = 0; i < ARRAY_SIZE(cw->data.array); i++) 970 bt_ctf_field_type_put(cw->data.array[i]); 971 } 972 973 static int ctf_writer__init_data(struct ctf_writer *cw) 974 { 975 #define CREATE_INT_TYPE(type, size, sign, hex) \ 976 do { \ 977 (type) = create_int_type(size, sign, hex); \ 978 if (!(type)) \ 979 goto err; \ 980 } while (0) 981 982 CREATE_INT_TYPE(cw->data.s64, 64, true, false); 983 CREATE_INT_TYPE(cw->data.u64, 64, false, false); 984 CREATE_INT_TYPE(cw->data.s32, 32, true, false); 985 CREATE_INT_TYPE(cw->data.u32, 32, false, false); 986 CREATE_INT_TYPE(cw->data.u32_hex, 32, false, true); 987 CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true); 988 989 cw->data.string = bt_ctf_field_type_string_create(); 990 if (cw->data.string) 991 return 0; 992 993 err: 994 ctf_writer__cleanup_data(cw); 995 pr_err("Failed to create data types.\n"); 996 return -1; 997 } 998 999 static void ctf_writer__cleanup(struct ctf_writer *cw) 1000 { 1001 ctf_writer__cleanup_data(cw); 1002 1003 bt_ctf_clock_put(cw->clock); 1004 free_streams(cw); 1005 bt_ctf_stream_class_put(cw->stream_class); 1006 bt_ctf_writer_put(cw->writer); 1007 1008 /* and NULL all the pointers */ 1009 memset(cw, 0, sizeof(*cw)); 1010 } 1011 1012 static int ctf_writer__init(struct ctf_writer *cw, const char *path) 1013 { 1014 struct bt_ctf_writer *writer; 1015 struct bt_ctf_stream_class *stream_class; 1016 struct bt_ctf_clock *clock; 1017 struct bt_ctf_field_type *pkt_ctx_type; 1018 int ret; 1019 1020 /* CTF writer */ 1021 writer = bt_ctf_writer_create(path); 1022 if (!writer) 1023 goto err; 1024 1025 cw->writer = writer; 1026 1027 /* CTF clock */ 1028 clock = bt_ctf_clock_create("perf_clock"); 1029 if (!clock) { 1030 pr("Failed to create CTF clock.\n"); 1031 goto err_cleanup; 1032 } 1033 1034 cw->clock = clock; 1035 1036 if (ctf_writer__setup_clock(cw)) { 1037 pr("Failed to setup CTF clock.\n"); 1038 goto err_cleanup; 1039 } 1040 1041 /* CTF stream class */ 1042 stream_class = bt_ctf_stream_class_create("perf_stream"); 1043 if (!stream_class) { 1044 pr("Failed to create CTF stream class.\n"); 1045 goto err_cleanup; 1046 } 1047 1048 cw->stream_class = stream_class; 1049 1050 /* CTF clock stream setup */ 1051 if (bt_ctf_stream_class_set_clock(stream_class, clock)) { 1052 pr("Failed to assign CTF clock to stream class.\n"); 1053 goto err_cleanup; 1054 } 1055 1056 if (ctf_writer__init_data(cw)) 1057 goto err_cleanup; 1058 1059 /* Add cpu_id for packet context */ 1060 pkt_ctx_type = bt_ctf_stream_class_get_packet_context_type(stream_class); 1061 if (!pkt_ctx_type) 1062 goto err_cleanup; 1063 1064 ret = bt_ctf_field_type_structure_add_field(pkt_ctx_type, cw->data.u32, "cpu_id"); 1065 bt_ctf_field_type_put(pkt_ctx_type); 1066 if (ret) 1067 goto err_cleanup; 1068 1069 /* CTF clock writer setup */ 1070 if (bt_ctf_writer_add_clock(writer, clock)) { 1071 pr("Failed to assign CTF clock to writer.\n"); 1072 goto err_cleanup; 1073 } 1074 1075 return 0; 1076 1077 err_cleanup: 1078 ctf_writer__cleanup(cw); 1079 err: 1080 pr_err("Failed to setup CTF writer.\n"); 1081 return -1; 1082 } 1083 1084 static int ctf_writer__flush_streams(struct ctf_writer *cw) 1085 { 1086 int cpu, ret = 0; 1087 1088 for (cpu = 0; cpu < cw->stream_cnt && !ret; cpu++) 1089 ret = ctf_stream__flush(cw->stream[cpu]); 1090 1091 return ret; 1092 } 1093 1094 static int convert__config(const char *var, const char *value, void *cb) 1095 { 1096 struct convert *c = cb; 1097 1098 if (!strcmp(var, "convert.queue-size")) { 1099 c->queue_size = perf_config_u64(var, value); 1100 return 0; 1101 } 1102 1103 return perf_default_config(var, value, cb); 1104 } 1105 1106 int bt_convert__perf2ctf(const char *input, const char *path, bool force) 1107 { 1108 struct perf_session *session; 1109 struct perf_data_file file = { 1110 .path = input, 1111 .mode = PERF_DATA_MODE_READ, 1112 .force = force, 1113 }; 1114 struct convert c = { 1115 .tool = { 1116 .sample = process_sample_event, 1117 .mmap = perf_event__process_mmap, 1118 .mmap2 = perf_event__process_mmap2, 1119 .comm = perf_event__process_comm, 1120 .exit = perf_event__process_exit, 1121 .fork = perf_event__process_fork, 1122 .lost = perf_event__process_lost, 1123 .tracing_data = perf_event__process_tracing_data, 1124 .build_id = perf_event__process_build_id, 1125 .ordered_events = true, 1126 .ordering_requires_timestamps = true, 1127 }, 1128 }; 1129 struct ctf_writer *cw = &c.writer; 1130 int err = -1; 1131 1132 perf_config(convert__config, &c); 1133 1134 /* CTF writer */ 1135 if (ctf_writer__init(cw, path)) 1136 return -1; 1137 1138 /* perf.data session */ 1139 session = perf_session__new(&file, 0, &c.tool); 1140 if (!session) 1141 goto free_writer; 1142 1143 if (c.queue_size) { 1144 ordered_events__set_alloc_size(&session->ordered_events, 1145 c.queue_size); 1146 } 1147 1148 /* CTF writer env/clock setup */ 1149 if (ctf_writer__setup_env(cw, session)) 1150 goto free_session; 1151 1152 /* CTF events setup */ 1153 if (setup_events(cw, session)) 1154 goto free_session; 1155 1156 if (setup_streams(cw, session)) 1157 goto free_session; 1158 1159 err = perf_session__process_events(session); 1160 if (!err) 1161 err = ctf_writer__flush_streams(cw); 1162 else 1163 pr_err("Error during conversion.\n"); 1164 1165 fprintf(stderr, 1166 "[ perf data convert: Converted '%s' into CTF data '%s' ]\n", 1167 file.path, path); 1168 1169 fprintf(stderr, 1170 "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples) ]\n", 1171 (double) c.events_size / 1024.0 / 1024.0, 1172 c.events_count); 1173 1174 perf_session__delete(session); 1175 ctf_writer__cleanup(cw); 1176 1177 return err; 1178 1179 free_session: 1180 perf_session__delete(session); 1181 free_writer: 1182 ctf_writer__cleanup(cw); 1183 pr_err("Error during conversion setup.\n"); 1184 return err; 1185 } 1186