Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

New features:

- Allow passing C language eBPF scriptlets via --event in all tools,
so that it gets built using clang and then pass it to the kernel via
sys_bpf(). (Wang Nan)

- Wire up the loaded ebpf object file with associated kprobes, so that
it can determine if the kprobes will be filtered or not. (Wang Nan)

User visible changes:

- Add cmd string table to decode sys_bpf first arg in 'trace'. (Arnaldo Carvalho de Melo)

- Enable printing of branch stack in 'perf script'. (Stephane Eranian)

- Pass the right file with debug info to libunwind. (Rabin Vincent)

Build Fixes:

- Make sure fixdep is built before libbpf, fixing a race. (Jiri Olsa)

- Fix libiberty feature detection. (Rabin Vincent)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>

+227 -16
+2 -2
tools/build/feature/Makefile
··· 132 132 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl 133 133 134 134 test-liberty.bin: 135 - $(CC) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty 135 + $(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty 136 136 137 137 test-liberty-z.bin: 138 - $(CC) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz 138 + $(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty -lz 139 139 140 140 test-cplus-demangle.bin: 141 141 $(BUILD) -liberty
+6
tools/perf/Documentation/perf-record.txt
··· 314 314 Record context switch events i.e. events of type PERF_RECORD_SWITCH or 315 315 PERF_RECORD_SWITCH_CPU_WIDE. 316 316 317 + --clang-path:: 318 + Path to clang binary to use for compiling BPF scriptlets. 319 + 320 + --clang-opt:: 321 + Options passed to clang when compiling BPF scriptlets. 322 + 317 323 SEE ALSO 318 324 -------- 319 325 linkperf:perf-stat[1], linkperf:perf-list[1]
+12 -2
tools/perf/Documentation/perf-script.txt
··· 112 112 --debug-mode:: 113 113 Do various checks like samples ordering and lost events. 114 114 115 - -f:: 115 + -F:: 116 116 --fields:: 117 117 Comma separated list of fields to print. Options are: 118 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, 119 - srcline, period, iregs, flags. 119 + srcline, period, iregs, brstack, brstacksym, flags. 120 120 Field list can be prepended with the type, trace, sw or hw, 121 121 to indicate to which event type the field list applies. 122 122 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace ··· 174 174 175 175 Finally, a user may not set fields to none for all event types. 176 176 i.e., -f "" is not allowed. 177 + 178 + The brstack output includes branch related information with raw addresses using the 179 + /v/v/v/v/ syntax in the following order: 180 + FROM: branch source instruction 181 + TO : branch target instruction 182 + M/P/-: M=branch target mispredicted or branch direction was mispredicted, P=target predicted or direction predicted, -=not supported 183 + X/- : X=branch inside a transactional region, -=not in transaction region or not supported 184 + A/- : A=TSX abort entry, -=not aborted region or not supported 185 + 186 + The brstacksym is identical to brstack, except that the FROM and TO addresses are printed in a symbolic form if possible. 177 187 178 188 -k:: 179 189 --vmlinux=<file>::
+1 -1
tools/perf/Makefile.perf
··· 430 430 $(call QUIET_CLEAN, libapi) 431 431 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null 432 432 433 - $(LIBBPF): FORCE 433 + $(LIBBPF): fixdep FORCE 434 434 $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) $(OUTPUT)libbpf.a 435 435 436 436 $(LIBBPF)-clean:
+7
tools/perf/builtin-record.c
··· 31 31 #include "util/auxtrace.h" 32 32 #include "util/parse-branch-options.h" 33 33 #include "util/parse-regs-options.h" 34 + #include "util/llvm-utils.h" 34 35 35 36 #include <unistd.h> 36 37 #include <sched.h> ··· 1113 1112 "per thread proc mmap processing timeout in ms"), 1114 1113 OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1115 1114 "Record context switch events"), 1115 + #ifdef HAVE_LIBBPF_SUPPORT 1116 + OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 1117 + "clang binary to use for compiling BPF scriptlets"), 1118 + OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 1119 + "options passed to clang when compiling BPF scriptlets"), 1120 + #endif 1116 1121 OPT_END() 1117 1122 }; 1118 1123
+81 -1
tools/perf/builtin-script.c
··· 51 51 PERF_OUTPUT_SRCLINE = 1U << 12, 52 52 PERF_OUTPUT_PERIOD = 1U << 13, 53 53 PERF_OUTPUT_IREGS = 1U << 14, 54 + PERF_OUTPUT_BRSTACK = 1U << 15, 55 + PERF_OUTPUT_BRSTACKSYM = 1U << 16, 54 56 }; 55 57 56 58 struct output_option { ··· 74 72 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, 75 73 {.str = "period", .field = PERF_OUTPUT_PERIOD}, 76 74 {.str = "iregs", .field = PERF_OUTPUT_IREGS}, 75 + {.str = "brstack", .field = PERF_OUTPUT_BRSTACK}, 76 + {.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM}, 77 77 }; 78 78 79 79 /* default set to maintain compatibility with current format */ ··· 429 425 } 430 426 } 431 427 428 + static inline char 429 + mispred_str(struct branch_entry *br) 430 + { 431 + if (!(br->flags.mispred || br->flags.predicted)) 432 + return '-'; 433 + 434 + return br->flags.predicted ? 'P' : 'M'; 435 + } 436 + 437 + static void print_sample_brstack(union perf_event *event __maybe_unused, 438 + struct perf_sample *sample, 439 + struct thread *thread __maybe_unused, 440 + struct perf_event_attr *attr __maybe_unused) 441 + { 442 + struct branch_stack *br = sample->branch_stack; 443 + u64 i; 444 + 445 + if (!(br && br->nr)) 446 + return; 447 + 448 + for (i = 0; i < br->nr; i++) { 449 + printf(" 0x%"PRIx64"/0x%"PRIx64"/%c/%c/%c/%d ", 450 + br->entries[i].from, 451 + br->entries[i].to, 452 + mispred_str( br->entries + i), 453 + br->entries[i].flags.in_tx? 'X' : '-', 454 + br->entries[i].flags.abort? 'A' : '-', 455 + br->entries[i].flags.cycles); 456 + } 457 + } 458 + 459 + static void print_sample_brstacksym(union perf_event *event __maybe_unused, 460 + struct perf_sample *sample, 461 + struct thread *thread __maybe_unused, 462 + struct perf_event_attr *attr __maybe_unused) 463 + { 464 + struct branch_stack *br = sample->branch_stack; 465 + struct addr_location alf, alt; 466 + u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 467 + u64 i, from, to; 468 + 469 + if (!(br && br->nr)) 470 + return; 471 + 472 + for (i = 0; i < br->nr; i++) { 473 + 474 + memset(&alf, 0, sizeof(alf)); 475 + memset(&alt, 0, sizeof(alt)); 476 + from = br->entries[i].from; 477 + to = br->entries[i].to; 478 + 479 + thread__find_addr_map(thread, cpumode, MAP__FUNCTION, from, &alf); 480 + if (alf.map) 481 + alf.sym = map__find_symbol(alf.map, alf.addr, NULL); 482 + 483 + thread__find_addr_map(thread, cpumode, MAP__FUNCTION, to, &alt); 484 + if (alt.map) 485 + alt.sym = map__find_symbol(alt.map, alt.addr, NULL); 486 + 487 + symbol__fprintf_symname_offs(alf.sym, &alf, stdout); 488 + putchar('/'); 489 + symbol__fprintf_symname_offs(alt.sym, &alt, stdout); 490 + printf("/%c/%c/%c/%d ", 491 + mispred_str( br->entries + i), 492 + br->entries[i].flags.in_tx? 'X' : '-', 493 + br->entries[i].flags.abort? 'A' : '-', 494 + br->entries[i].flags.cycles); 495 + } 496 + } 497 + 498 + 432 499 static void print_sample_addr(union perf_event *event, 433 500 struct perf_sample *sample, 434 501 struct thread *thread, ··· 634 559 635 560 if (PRINT_FIELD(IREGS)) 636 561 print_sample_iregs(event, sample, thread, attr); 562 + 563 + if (PRINT_FIELD(BRSTACK)) 564 + print_sample_brstack(event, sample, thread, attr); 565 + else if (PRINT_FIELD(BRSTACKSYM)) 566 + print_sample_brstacksym(event, sample, thread, attr); 637 567 638 568 printf("\n"); 639 569 } ··· 1761 1681 "comma separated output fields prepend with 'type:'. " 1762 1682 "Valid types: hw,sw,trace,raw. " 1763 1683 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 1764 - "addr,symoff,period,iregs,flags", parse_output_fields), 1684 + "addr,symoff,period,iregs,brstack,brstacksym,flags", parse_output_fields), 1765 1685 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1766 1686 "system-wide collection from all CPUs"), 1767 1687 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
+7
tools/perf/builtin-trace.c
··· 585 585 586 586 #define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op 587 587 588 + static const char *bpf_cmd[] = { 589 + "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM", 590 + "MAP_GET_NEXT_KEY", "PROG_LOAD", 591 + }; 592 + static DEFINE_STRARRAY(bpf_cmd); 593 + 588 594 static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", }; 589 595 static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1); 590 596 ··· 1017 1011 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ 1018 1012 [1] = SCA_ACCMODE, /* mode */ }, }, 1019 1013 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, 1014 + { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), }, 1020 1015 { .name = "brk", .hexret = true, 1021 1016 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, 1022 1017 { .name = "chdir", .errmsg = true,
+44
tools/perf/tests/bpf-script-example.c
··· 1 + #ifndef LINUX_VERSION_CODE 2 + # error Need LINUX_VERSION_CODE 3 + # error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig' 4 + #endif 5 + #define BPF_ANY 0 6 + #define BPF_MAP_TYPE_ARRAY 2 7 + #define BPF_FUNC_map_lookup_elem 1 8 + #define BPF_FUNC_map_update_elem 2 9 + 10 + static void *(*bpf_map_lookup_elem)(void *map, void *key) = 11 + (void *) BPF_FUNC_map_lookup_elem; 12 + static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) = 13 + (void *) BPF_FUNC_map_update_elem; 14 + 15 + struct bpf_map_def { 16 + unsigned int type; 17 + unsigned int key_size; 18 + unsigned int value_size; 19 + unsigned int max_entries; 20 + }; 21 + 22 + #define SEC(NAME) __attribute__((section(NAME), used)) 23 + struct bpf_map_def SEC("maps") flip_table = { 24 + .type = BPF_MAP_TYPE_ARRAY, 25 + .key_size = sizeof(int), 26 + .value_size = sizeof(int), 27 + .max_entries = 1, 28 + }; 29 + 30 + SEC("func=sys_epoll_pwait") 31 + int bpf_func__sys_epoll_pwait(void *ctx) 32 + { 33 + int ind =0; 34 + int *flag = bpf_map_lookup_elem(&flip_table, &ind); 35 + int new_flag; 36 + if (!flag) 37 + return 0; 38 + /* flip flag and store back */ 39 + new_flag = !*flag; 40 + bpf_map_update_elem(&flip_table, &ind, &new_flag, BPF_ANY); 41 + return new_flag; 42 + } 43 + char _license[] SEC("license") = "GPL"; 44 + int _version SEC("version") = LINUX_VERSION_CODE;
+15 -2
tools/perf/util/bpf-loader.c
··· 12 12 #include "bpf-loader.h" 13 13 #include "probe-event.h" 14 14 #include "probe-finder.h" // for MAX_PROBES 15 + #include "llvm-utils.h" 15 16 16 17 #define DEFINE_PRINT_FN(name, level) \ 17 18 static int libbpf_##name(const char *fmt, ...) \ ··· 34 33 struct perf_probe_event pev; 35 34 }; 36 35 37 - struct bpf_object *bpf__prepare_load(const char *filename) 36 + struct bpf_object *bpf__prepare_load(const char *filename, bool source) 38 37 { 39 38 struct bpf_object *obj; 40 39 static bool libbpf_initialized; ··· 46 45 libbpf_initialized = true; 47 46 } 48 47 49 - obj = bpf_object__open(filename); 48 + if (source) { 49 + int err; 50 + void *obj_buf; 51 + size_t obj_buf_sz; 52 + 53 + err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz); 54 + if (err) 55 + return ERR_PTR(err); 56 + obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename); 57 + free(obj_buf); 58 + } else 59 + obj = bpf_object__open(filename); 60 + 50 61 if (!obj) { 51 62 pr_debug("bpf: failed to load %s\n", filename); 52 63 return ERR_PTR(-EINVAL);
+3 -2
tools/perf/util/bpf-loader.h
··· 18 18 int fd, void *arg); 19 19 20 20 #ifdef HAVE_LIBBPF_SUPPORT 21 - struct bpf_object *bpf__prepare_load(const char *filename); 21 + struct bpf_object *bpf__prepare_load(const char *filename, bool source); 22 22 23 23 void bpf__clear(void); 24 24 ··· 34 34 bpf_prog_iter_callback_t func, void *arg); 35 35 #else 36 36 static inline struct bpf_object * 37 - bpf__prepare_load(const char *filename __maybe_unused) 37 + bpf__prepare_load(const char *filename __maybe_unused, 38 + bool source __maybe_unused) 38 39 { 39 40 pr_debug("ERROR: eBPF object loading is disabled during compiling.\n"); 40 41 return ERR_PTR(-ENOTSUP);
+17
tools/perf/util/evsel.c
··· 208 208 evsel->unit = ""; 209 209 evsel->scale = 1.0; 210 210 evsel->evlist = NULL; 211 + evsel->bpf_fd = -1; 211 212 INIT_LIST_HEAD(&evsel->node); 212 213 INIT_LIST_HEAD(&evsel->config_terms); 213 214 perf_evsel__object.init(evsel); ··· 1357 1356 err); 1358 1357 goto try_fallback; 1359 1358 } 1359 + 1360 + if (evsel->bpf_fd >= 0) { 1361 + int evt_fd = FD(evsel, cpu, thread); 1362 + int bpf_fd = evsel->bpf_fd; 1363 + 1364 + err = ioctl(evt_fd, 1365 + PERF_EVENT_IOC_SET_BPF, 1366 + bpf_fd); 1367 + if (err && errno != EEXIST) { 1368 + pr_err("failed to attach bpf fd %d: %s\n", 1369 + bpf_fd, strerror(errno)); 1370 + err = -EINVAL; 1371 + goto out_close; 1372 + } 1373 + } 1374 + 1360 1375 set_rlimit = NO_CHANGE; 1361 1376 1362 1377 /*
+1
tools/perf/util/evsel.h
··· 123 123 char *group_name; 124 124 bool cmdline_group_boundary; 125 125 struct list_head config_terms; 126 + int bpf_fd; 126 127 }; 127 128 128 129 union u64_swap {
+9 -2
tools/perf/util/parse-events.c
··· 542 542 struct __add_bpf_event_param *param = _param; 543 543 struct parse_events_evlist *evlist = param->data; 544 544 struct list_head *list = param->list; 545 + struct perf_evsel *pos; 545 546 int err; 546 547 547 548 pr_debug("add bpf event %s:%s and attach bpf program %d\n", ··· 563 562 } 564 563 pr_debug("adding %s:%s\n", tev->group, tev->event); 565 564 565 + list_for_each_entry(pos, &new_evsels, node) { 566 + pr_debug("adding %s:%s to %p\n", 567 + tev->group, tev->event, pos); 568 + pos->bpf_fd = fd; 569 + } 566 570 list_splice(&new_evsels, list); 567 571 return 0; 568 572 } ··· 626 620 627 621 int parse_events_load_bpf(struct parse_events_evlist *data, 628 622 struct list_head *list, 629 - char *bpf_file_name) 623 + char *bpf_file_name, 624 + bool source) 630 625 { 631 626 struct bpf_object *obj; 632 627 633 - obj = bpf__prepare_load(bpf_file_name); 628 + obj = bpf__prepare_load(bpf_file_name, source); 634 629 if (IS_ERR(obj) || !obj) { 635 630 char errbuf[BUFSIZ]; 636 631 int err;
+2 -1
tools/perf/util/parse-events.h
··· 125 125 struct list_head *head_config); 126 126 int parse_events_load_bpf(struct parse_events_evlist *data, 127 127 struct list_head *list, 128 - char *bpf_file_name); 128 + char *bpf_file_name, 129 + bool source); 129 130 /* Provide this function for perf test */ 130 131 struct bpf_object; 131 132 int parse_events_load_bpf_obj(struct parse_events_evlist *data,
+3
tools/perf/util/parse-events.l
··· 116 116 event_pmu [^,{}/]+[/][^/]*[/][^,{}/]* 117 117 event [^,{}/]+ 118 118 bpf_object .*\.(o|bpf) 119 + bpf_source .*\.c 119 120 120 121 num_dec [0-9]+ 121 122 num_hex 0x[a-fA-F0-9]+ ··· 162 161 163 162 {event_pmu} | 164 163 {bpf_object} | 164 + {bpf_source} | 165 165 {event} { 166 166 BEGIN(INITIAL); 167 167 REWIND(1); ··· 271 269 272 270 {modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } 273 271 {bpf_object} { return str(yyscanner, PE_BPF_OBJECT); } 272 + {bpf_source} { return str(yyscanner, PE_BPF_SOURCE); } 274 273 {name} { return pmu_str_check(yyscanner); } 275 274 "/" { BEGIN(config); return '/'; } 276 275 - { return '-'; }
+13 -2
tools/perf/util/parse-events.y
··· 42 42 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM 43 43 %token PE_EVENT_NAME 44 44 %token PE_NAME 45 - %token PE_BPF_OBJECT 45 + %token PE_BPF_OBJECT PE_BPF_SOURCE 46 46 %token PE_MODIFIER_EVENT PE_MODIFIER_BP 47 47 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 48 48 %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP ··· 55 55 %type <num> PE_TERM 56 56 %type <str> PE_NAME 57 57 %type <str> PE_BPF_OBJECT 58 + %type <str> PE_BPF_SOURCE 58 59 %type <str> PE_NAME_CACHE_TYPE 59 60 %type <str> PE_NAME_CACHE_OP_RESULT 60 61 %type <str> PE_MODIFIER_EVENT ··· 462 461 struct list_head *list; 463 462 464 463 ALLOC_LIST(list); 465 - ABORT_ON(parse_events_load_bpf(data, list, $1)); 464 + ABORT_ON(parse_events_load_bpf(data, list, $1, false)); 465 + $$ = list; 466 + } 467 + | 468 + PE_BPF_SOURCE 469 + { 470 + struct parse_events_evlist *data = _data; 471 + struct list_head *list; 472 + 473 + ALLOC_LIST(list); 474 + ABORT_ON(parse_events_load_bpf(data, list, $1, true)); 466 475 $$ = list; 467 476 } 468 477
+4 -1
tools/perf/util/unwind-libunwind.c
··· 360 360 int fd = dso__data_get_fd(map->dso, ui->machine); 361 361 int is_exec = elf_is_exec(fd, map->dso->name); 362 362 unw_word_t base = is_exec ? 0 : map->start; 363 + const char *symfile; 363 364 364 365 if (fd >= 0) 365 366 dso__data_put_fd(map->dso); 366 367 368 + symfile = map->dso->symsrc_filename ?: map->dso->name; 369 + 367 370 memset(&di, 0, sizeof(di)); 368 - if (dwarf_find_debug_frame(0, &di, ip, base, map->dso->name, 371 + if (dwarf_find_debug_frame(0, &di, ip, base, symfile, 369 372 map->start, map->end)) 370 373 return dwarf_search_unwind_table(as, ip, &di, pi, 371 374 need_unwind_info, arg);