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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf fixes from Ingo Molnar:
"On the kernel side there's two x86 PMU driver fixes and a uprobes fix,
plus on the tooling side there's a number of fixes and some late
updates"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (36 commits)
perf sched timehist: Fix invalid period calculation
perf sched timehist: Remove hardcoded 'comm_width' check at print_summary
perf sched timehist: Enlarge default 'comm_width'
perf sched timehist: Honour 'comm_width' when aligning the headers
perf/x86: Fix overlap counter scheduling bug
perf/x86/pebs: Fix handling of PEBS buffer overflows
samples/bpf: Move open_raw_sock to separate header
samples/bpf: Remove perf_event_open() declaration
samples/bpf: Be consistent with bpf_load_program bpf_insn parameter
tools lib bpf: Add bpf_prog_{attach,detach}
samples/bpf: Switch over to libbpf
perf diff: Do not overwrite valid build id
perf annotate: Don't throw error for zero length symbols
perf bench futex: Fix lock-pi help string
perf trace: Check if MAP_32BIT is defined (again)
samples/bpf: Make perf_event_read() static
uprobes: Fix uprobes on MIPS, allow for a cache flush after ixol breakpoint creation
samples/bpf: Make samples more libbpf-centric
tools lib bpf: Add flags to bpf_create_map()
tools lib bpf: use __u32 from linux/types.h
...

+1105 -751
+21 -9
arch/x86/events/intel/core.c
··· 2110 2110 GLOBAL_STATUS_LBRS_FROZEN); 2111 2111 if (!status) 2112 2112 goto done; 2113 + /* 2114 + * In case multiple PEBS events are sampled at the same time, 2115 + * it is possible to have GLOBAL_STATUS bit 62 set indicating 2116 + * PEBS buffer overflow and also seeing at most 3 PEBS counters 2117 + * having their bits set in the status register. This is a sign 2118 + * that there was at least one PEBS record pending at the time 2119 + * of the PMU interrupt. PEBS counters must only be processed 2120 + * via the drain_pebs() calls and not via the regular sample 2121 + * processing loop coming after that the function, otherwise 2122 + * phony regular samples may be generated in the sampling buffer 2123 + * not marked with the EXACT tag. Another possibility is to have 2124 + * one PEBS event and at least one non-PEBS event whic hoverflows 2125 + * while PEBS has armed. In this case, bit 62 of GLOBAL_STATUS will 2126 + * not be set, yet the overflow status bit for the PEBS counter will 2127 + * be on Skylake. 2128 + * 2129 + * To avoid this problem, we systematically ignore the PEBS-enabled 2130 + * counters from the GLOBAL_STATUS mask and we always process PEBS 2131 + * events via drain_pebs(). 2132 + */ 2133 + status &= ~cpuc->pebs_enabled; 2113 2134 2114 2135 /* 2115 2136 * PEBS overflow sets bit 62 in the global status register ··· 2138 2117 if (__test_and_clear_bit(62, (unsigned long *)&status)) { 2139 2118 handled++; 2140 2119 x86_pmu.drain_pebs(regs); 2141 - /* 2142 - * There are cases where, even though, the PEBS ovfl bit is set 2143 - * in GLOBAL_OVF_STATUS, the PEBS events may also have their 2144 - * overflow bits set for their counters. We must clear them 2145 - * here because they have been processed as exact samples in 2146 - * the drain_pebs() routine. They must not be processed again 2147 - * in the for_each_bit_set() loop for regular samples below. 2148 - */ 2149 - status &= ~cpuc->pebs_enabled; 2150 2120 status &= x86_pmu.intel_ctrl | GLOBAL_STATUS_TRACE_TOPAPMI; 2151 2121 } 2152 2122
+1 -1
arch/x86/events/intel/uncore_snbep.c
··· 669 669 UNCORE_EVENT_CONSTRAINT(0x1c, 0xc), 670 670 UNCORE_EVENT_CONSTRAINT(0x1d, 0xc), 671 671 UNCORE_EVENT_CONSTRAINT(0x1e, 0xc), 672 - EVENT_CONSTRAINT_OVERLAP(0x1f, 0xe, 0xff), 672 + UNCORE_EVENT_CONSTRAINT(0x1f, 0xe), 673 673 UNCORE_EVENT_CONSTRAINT(0x21, 0x3), 674 674 UNCORE_EVENT_CONSTRAINT(0x23, 0x3), 675 675 UNCORE_EVENT_CONSTRAINT(0x31, 0x3),
+1 -1
kernel/events/uprobes.c
··· 1194 1194 /* Reserve the 1st slot for get_trampoline_vaddr() */ 1195 1195 set_bit(0, area->bitmap); 1196 1196 atomic_set(&area->slot_count, 1); 1197 - copy_to_page(area->pages[0], 0, &insn, UPROBE_SWBP_INSN_SIZE); 1197 + arch_uprobe_copy_ixol(area->pages[0], 0, &insn, UPROBE_SWBP_INSN_SIZE); 1198 1198 1199 1199 if (!xol_add_vma(mm, area)) 1200 1200 return area;
+38 -32
samples/bpf/Makefile
··· 35 35 hostprogs-y += lwt_len_hist 36 36 hostprogs-y += xdp_tx_iptunnel 37 37 38 - test_lru_dist-objs := test_lru_dist.o libbpf.o 39 - sock_example-objs := sock_example.o libbpf.o 40 - fds_example-objs := bpf_load.o libbpf.o fds_example.o 41 - sockex1-objs := bpf_load.o libbpf.o sockex1_user.o 42 - sockex2-objs := bpf_load.o libbpf.o sockex2_user.o 43 - sockex3-objs := bpf_load.o libbpf.o sockex3_user.o 44 - tracex1-objs := bpf_load.o libbpf.o tracex1_user.o 45 - tracex2-objs := bpf_load.o libbpf.o tracex2_user.o 46 - tracex3-objs := bpf_load.o libbpf.o tracex3_user.o 47 - tracex4-objs := bpf_load.o libbpf.o tracex4_user.o 48 - tracex5-objs := bpf_load.o libbpf.o tracex5_user.o 49 - tracex6-objs := bpf_load.o libbpf.o tracex6_user.o 50 - test_probe_write_user-objs := bpf_load.o libbpf.o test_probe_write_user_user.o 51 - trace_output-objs := bpf_load.o libbpf.o trace_output_user.o 52 - lathist-objs := bpf_load.o libbpf.o lathist_user.o 53 - offwaketime-objs := bpf_load.o libbpf.o offwaketime_user.o 54 - spintest-objs := bpf_load.o libbpf.o spintest_user.o 55 - map_perf_test-objs := bpf_load.o libbpf.o map_perf_test_user.o 56 - test_overhead-objs := bpf_load.o libbpf.o test_overhead_user.o 57 - test_cgrp2_array_pin-objs := libbpf.o test_cgrp2_array_pin.o 58 - test_cgrp2_attach-objs := libbpf.o test_cgrp2_attach.o 59 - test_cgrp2_attach2-objs := libbpf.o test_cgrp2_attach2.o cgroup_helpers.o 60 - test_cgrp2_sock-objs := libbpf.o test_cgrp2_sock.o 61 - test_cgrp2_sock2-objs := bpf_load.o libbpf.o test_cgrp2_sock2.o 62 - xdp1-objs := bpf_load.o libbpf.o xdp1_user.o 38 + # Libbpf dependencies 39 + LIBBPF := ../../tools/lib/bpf/bpf.o 40 + 41 + test_lru_dist-objs := test_lru_dist.o $(LIBBPF) 42 + sock_example-objs := sock_example.o $(LIBBPF) 43 + fds_example-objs := bpf_load.o $(LIBBPF) fds_example.o 44 + sockex1-objs := bpf_load.o $(LIBBPF) sockex1_user.o 45 + sockex2-objs := bpf_load.o $(LIBBPF) sockex2_user.o 46 + sockex3-objs := bpf_load.o $(LIBBPF) sockex3_user.o 47 + tracex1-objs := bpf_load.o $(LIBBPF) tracex1_user.o 48 + tracex2-objs := bpf_load.o $(LIBBPF) tracex2_user.o 49 + tracex3-objs := bpf_load.o $(LIBBPF) tracex3_user.o 50 + tracex4-objs := bpf_load.o $(LIBBPF) tracex4_user.o 51 + tracex5-objs := bpf_load.o $(LIBBPF) tracex5_user.o 52 + tracex6-objs := bpf_load.o $(LIBBPF) tracex6_user.o 53 + test_probe_write_user-objs := bpf_load.o $(LIBBPF) test_probe_write_user_user.o 54 + trace_output-objs := bpf_load.o $(LIBBPF) trace_output_user.o 55 + lathist-objs := bpf_load.o $(LIBBPF) lathist_user.o 56 + offwaketime-objs := bpf_load.o $(LIBBPF) offwaketime_user.o 57 + spintest-objs := bpf_load.o $(LIBBPF) spintest_user.o 58 + map_perf_test-objs := bpf_load.o $(LIBBPF) map_perf_test_user.o 59 + test_overhead-objs := bpf_load.o $(LIBBPF) test_overhead_user.o 60 + test_cgrp2_array_pin-objs := $(LIBBPF) test_cgrp2_array_pin.o 61 + test_cgrp2_attach-objs := $(LIBBPF) test_cgrp2_attach.o 62 + test_cgrp2_attach2-objs := $(LIBBPF) test_cgrp2_attach2.o cgroup_helpers.o 63 + test_cgrp2_sock-objs := $(LIBBPF) test_cgrp2_sock.o 64 + test_cgrp2_sock2-objs := bpf_load.o $(LIBBPF) test_cgrp2_sock2.o 65 + xdp1-objs := bpf_load.o $(LIBBPF) xdp1_user.o 63 66 # reuse xdp1 source intentionally 64 - xdp2-objs := bpf_load.o libbpf.o xdp1_user.o 65 - test_current_task_under_cgroup-objs := bpf_load.o libbpf.o cgroup_helpers.o \ 67 + xdp2-objs := bpf_load.o $(LIBBPF) xdp1_user.o 68 + test_current_task_under_cgroup-objs := bpf_load.o $(LIBBPF) cgroup_helpers.o \ 66 69 test_current_task_under_cgroup_user.o 67 - trace_event-objs := bpf_load.o libbpf.o trace_event_user.o 68 - sampleip-objs := bpf_load.o libbpf.o sampleip_user.o 69 - tc_l2_redirect-objs := bpf_load.o libbpf.o tc_l2_redirect_user.o 70 - lwt_len_hist-objs := bpf_load.o libbpf.o lwt_len_hist_user.o 71 - xdp_tx_iptunnel-objs := bpf_load.o libbpf.o xdp_tx_iptunnel_user.o 70 + trace_event-objs := bpf_load.o $(LIBBPF) trace_event_user.o 71 + sampleip-objs := bpf_load.o $(LIBBPF) sampleip_user.o 72 + tc_l2_redirect-objs := bpf_load.o $(LIBBPF) tc_l2_redirect_user.o 73 + lwt_len_hist-objs := bpf_load.o $(LIBBPF) lwt_len_hist_user.o 74 + xdp_tx_iptunnel-objs := bpf_load.o $(LIBBPF) xdp_tx_iptunnel_user.o 72 75 73 76 # Tell kbuild to always build the programs 74 77 always := $(hostprogs-y) ··· 107 104 always += xdp_tx_iptunnel_kern.o 108 105 109 106 HOSTCFLAGS += -I$(objtree)/usr/include 107 + HOSTCFLAGS += -I$(srctree)/tools/lib/ 110 108 HOSTCFLAGS += -I$(srctree)/tools/testing/selftests/bpf/ 109 + HOSTCFLAGS += -I$(srctree)/tools/lib/ -I$(srctree)/tools/include 110 + HOSTCFLAGS += -I$(srctree)/tools/perf 111 111 112 112 HOSTCFLAGS_bpf_load.o += -I$(objtree)/usr/include -Wno-unused-variable 113 113 HOSTLOADLIBES_fds_example += -lelf
+2 -2
samples/bpf/README.rst
··· 1 1 eBPF sample programs 2 2 ==================== 3 3 4 - This directory contains a mini eBPF library, test stubs, verifier 5 - test-suite and examples for using eBPF. 4 + This directory contains a test stubs, verifier test-suite and examples 5 + for using eBPF. The examples use libbpf from tools/lib/bpf. 6 6 7 7 Build dependencies 8 8 ==================
+16 -5
samples/bpf/bpf_load.c
··· 22 22 #include <poll.h> 23 23 #include <ctype.h> 24 24 #include "libbpf.h" 25 - #include "bpf_helpers.h" 26 25 #include "bpf_load.h" 26 + #include "perf-sys.h" 27 27 28 28 #define DEBUGFS "/sys/kernel/debug/tracing/" 29 29 30 30 static char license[128]; 31 31 static int kern_version; 32 32 static bool processed_sec[128]; 33 + char bpf_log_buf[BPF_LOG_BUF_SIZE]; 33 34 int map_fd[MAX_MAPS]; 34 35 int prog_fd[MAX_PROGS]; 35 36 int event_fd[MAX_PROGS]; 36 37 int prog_cnt; 37 38 int prog_array_fd = -1; 38 39 40 + struct bpf_map_def { 41 + unsigned int type; 42 + unsigned int key_size; 43 + unsigned int value_size; 44 + unsigned int max_entries; 45 + unsigned int map_flags; 46 + }; 47 + 39 48 static int populate_prog_array(const char *event, int prog_fd) 40 49 { 41 50 int ind = atoi(event), err; 42 51 43 - err = bpf_update_elem(prog_array_fd, &ind, &prog_fd, BPF_ANY); 52 + err = bpf_map_update_elem(prog_array_fd, &ind, &prog_fd, BPF_ANY); 44 53 if (err < 0) { 45 54 printf("failed to store prog_fd in prog_array\n"); 46 55 return -1; ··· 67 58 bool is_perf_event = strncmp(event, "perf_event", 10) == 0; 68 59 bool is_cgroup_skb = strncmp(event, "cgroup/skb", 10) == 0; 69 60 bool is_cgroup_sk = strncmp(event, "cgroup/sock", 11) == 0; 61 + size_t insns_cnt = size / sizeof(struct bpf_insn); 70 62 enum bpf_prog_type prog_type; 71 63 char buf[256]; 72 64 int fd, efd, err, id; ··· 97 87 return -1; 98 88 } 99 89 100 - fd = bpf_prog_load(prog_type, prog, size, license, kern_version); 90 + fd = bpf_load_program(prog_type, prog, insns_cnt, license, kern_version, 91 + bpf_log_buf, BPF_LOG_BUF_SIZE); 101 92 if (fd < 0) { 102 - printf("bpf_prog_load() err=%d\n%s", errno, bpf_log_buf); 93 + printf("bpf_load_program() err=%d\n%s", errno, bpf_log_buf); 103 94 return -1; 104 95 } 105 96 ··· 180 169 id = atoi(buf); 181 170 attr.config = id; 182 171 183 - efd = perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0); 172 + efd = sys_perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0); 184 173 if (efd < 0) { 185 174 printf("event %d fd %d err %s\n", id, efd, strerror(errno)); 186 175 return -1;
+3
samples/bpf/bpf_load.h
··· 1 1 #ifndef __BPF_LOAD_H 2 2 #define __BPF_LOAD_H 3 3 4 + #include "libbpf.h" 5 + 4 6 #define MAX_MAPS 32 5 7 #define MAX_PROGS 32 6 8 7 9 extern int map_fd[MAX_MAPS]; 8 10 extern int prog_fd[MAX_PROGS]; 9 11 extern int event_fd[MAX_PROGS]; 12 + extern char bpf_log_buf[BPF_LOG_BUF_SIZE]; 10 13 extern int prog_cnt; 11 14 12 15 /* parses elf file compiled by llvm .c->.o
+8 -5
samples/bpf/fds_example.c
··· 14 14 15 15 #include "bpf_load.h" 16 16 #include "libbpf.h" 17 + #include "sock_example.h" 17 18 18 19 #define BPF_F_PIN (1 << 0) 19 20 #define BPF_F_GET (1 << 1) ··· 50 49 51 50 static int bpf_prog_create(const char *object) 52 51 { 53 - static const struct bpf_insn insns[] = { 52 + static struct bpf_insn insns[] = { 54 53 BPF_MOV64_IMM(BPF_REG_0, 1), 55 54 BPF_EXIT_INSN(), 56 55 }; 56 + size_t insns_cnt = sizeof(insns) / sizeof(struct bpf_insn); 57 57 58 58 if (object) { 59 59 assert(!load_bpf_file((char *)object)); 60 60 return prog_fd[0]; 61 61 } else { 62 - return bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, 63 - insns, sizeof(insns), "GPL", 0); 62 + return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, 63 + insns, insns_cnt, "GPL", 0, 64 + bpf_log_buf, BPF_LOG_BUF_SIZE); 64 65 } 65 66 } 66 67 ··· 86 83 } 87 84 88 85 if ((flags & BPF_F_KEY_VAL) == BPF_F_KEY_VAL) { 89 - ret = bpf_update_elem(fd, &key, &value, 0); 86 + ret = bpf_map_update_elem(fd, &key, &value, 0); 90 87 printf("bpf: fd:%d u->(%u:%u) ret:(%d,%s)\n", fd, key, value, 91 88 ret, strerror(errno)); 92 89 assert(ret == 0); 93 90 } else if (flags & BPF_F_KEY) { 94 - ret = bpf_lookup_elem(fd, &key, &value); 91 + ret = bpf_map_lookup_elem(fd, &key, &value); 95 92 printf("bpf: fd:%d l->(%u):%u ret:(%d,%s)\n", fd, key, value, 96 93 ret, strerror(errno)); 97 94 assert(ret == 0);
+1 -1
samples/bpf/lathist_user.c
··· 73 73 for (c = 0; c < MAX_CPU; c++) { 74 74 for (i = 0; i < MAX_ENTRIES; i++) { 75 75 key = c * MAX_ENTRIES + i; 76 - bpf_lookup_elem(fd, &key, &value); 76 + bpf_map_lookup_elem(fd, &key, &value); 77 77 78 78 cpu_hist[c].data[i] = value; 79 79 if (value > cpu_hist[c].max)
-176
samples/bpf/libbpf.c
··· 1 - /* eBPF mini library */ 2 - #include <stdlib.h> 3 - #include <stdio.h> 4 - #include <linux/unistd.h> 5 - #include <unistd.h> 6 - #include <string.h> 7 - #include <linux/netlink.h> 8 - #include <linux/bpf.h> 9 - #include <errno.h> 10 - #include <net/ethernet.h> 11 - #include <net/if.h> 12 - #include <linux/if_packet.h> 13 - #include <arpa/inet.h> 14 - #include "libbpf.h" 15 - 16 - static __u64 ptr_to_u64(void *ptr) 17 - { 18 - return (__u64) (unsigned long) ptr; 19 - } 20 - 21 - int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, 22 - int max_entries, int map_flags) 23 - { 24 - union bpf_attr attr = { 25 - .map_type = map_type, 26 - .key_size = key_size, 27 - .value_size = value_size, 28 - .max_entries = max_entries, 29 - .map_flags = map_flags, 30 - }; 31 - 32 - return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr)); 33 - } 34 - 35 - int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags) 36 - { 37 - union bpf_attr attr = { 38 - .map_fd = fd, 39 - .key = ptr_to_u64(key), 40 - .value = ptr_to_u64(value), 41 - .flags = flags, 42 - }; 43 - 44 - return syscall(__NR_bpf, BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)); 45 - } 46 - 47 - int bpf_lookup_elem(int fd, void *key, void *value) 48 - { 49 - union bpf_attr attr = { 50 - .map_fd = fd, 51 - .key = ptr_to_u64(key), 52 - .value = ptr_to_u64(value), 53 - }; 54 - 55 - return syscall(__NR_bpf, BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)); 56 - } 57 - 58 - int bpf_delete_elem(int fd, void *key) 59 - { 60 - union bpf_attr attr = { 61 - .map_fd = fd, 62 - .key = ptr_to_u64(key), 63 - }; 64 - 65 - return syscall(__NR_bpf, BPF_MAP_DELETE_ELEM, &attr, sizeof(attr)); 66 - } 67 - 68 - int bpf_get_next_key(int fd, void *key, void *next_key) 69 - { 70 - union bpf_attr attr = { 71 - .map_fd = fd, 72 - .key = ptr_to_u64(key), 73 - .next_key = ptr_to_u64(next_key), 74 - }; 75 - 76 - return syscall(__NR_bpf, BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr)); 77 - } 78 - 79 - #define ROUND_UP(x, n) (((x) + (n) - 1u) & ~((n) - 1u)) 80 - 81 - char bpf_log_buf[LOG_BUF_SIZE]; 82 - 83 - int bpf_prog_load(enum bpf_prog_type prog_type, 84 - const struct bpf_insn *insns, int prog_len, 85 - const char *license, int kern_version) 86 - { 87 - union bpf_attr attr = { 88 - .prog_type = prog_type, 89 - .insns = ptr_to_u64((void *) insns), 90 - .insn_cnt = prog_len / sizeof(struct bpf_insn), 91 - .license = ptr_to_u64((void *) license), 92 - .log_buf = ptr_to_u64(bpf_log_buf), 93 - .log_size = LOG_BUF_SIZE, 94 - .log_level = 1, 95 - }; 96 - 97 - /* assign one field outside of struct init to make sure any 98 - * padding is zero initialized 99 - */ 100 - attr.kern_version = kern_version; 101 - 102 - bpf_log_buf[0] = 0; 103 - 104 - return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); 105 - } 106 - 107 - int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type) 108 - { 109 - union bpf_attr attr = { 110 - .target_fd = target_fd, 111 - .attach_bpf_fd = prog_fd, 112 - .attach_type = type, 113 - }; 114 - 115 - return syscall(__NR_bpf, BPF_PROG_ATTACH, &attr, sizeof(attr)); 116 - } 117 - 118 - int bpf_prog_detach(int target_fd, enum bpf_attach_type type) 119 - { 120 - union bpf_attr attr = { 121 - .target_fd = target_fd, 122 - .attach_type = type, 123 - }; 124 - 125 - return syscall(__NR_bpf, BPF_PROG_DETACH, &attr, sizeof(attr)); 126 - } 127 - 128 - int bpf_obj_pin(int fd, const char *pathname) 129 - { 130 - union bpf_attr attr = { 131 - .pathname = ptr_to_u64((void *)pathname), 132 - .bpf_fd = fd, 133 - }; 134 - 135 - return syscall(__NR_bpf, BPF_OBJ_PIN, &attr, sizeof(attr)); 136 - } 137 - 138 - int bpf_obj_get(const char *pathname) 139 - { 140 - union bpf_attr attr = { 141 - .pathname = ptr_to_u64((void *)pathname), 142 - }; 143 - 144 - return syscall(__NR_bpf, BPF_OBJ_GET, &attr, sizeof(attr)); 145 - } 146 - 147 - int open_raw_sock(const char *name) 148 - { 149 - struct sockaddr_ll sll; 150 - int sock; 151 - 152 - sock = socket(PF_PACKET, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, htons(ETH_P_ALL)); 153 - if (sock < 0) { 154 - printf("cannot create raw socket\n"); 155 - return -1; 156 - } 157 - 158 - memset(&sll, 0, sizeof(sll)); 159 - sll.sll_family = AF_PACKET; 160 - sll.sll_ifindex = if_nametoindex(name); 161 - sll.sll_protocol = htons(ETH_P_ALL); 162 - if (bind(sock, (struct sockaddr *)&sll, sizeof(sll)) < 0) { 163 - printf("bind to %s: %s\n", name, strerror(errno)); 164 - close(sock); 165 - return -1; 166 - } 167 - 168 - return sock; 169 - } 170 - 171 - int perf_event_open(struct perf_event_attr *attr, int pid, int cpu, 172 - int group_fd, unsigned long flags) 173 - { 174 - return syscall(__NR_perf_event_open, attr, pid, cpu, 175 - group_fd, flags); 176 - }
+2 -26
samples/bpf/libbpf.h
··· 2 2 #ifndef __LIBBPF_H 3 3 #define __LIBBPF_H 4 4 5 + #include <bpf/bpf.h> 6 + 5 7 struct bpf_insn; 6 - 7 - int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, 8 - int max_entries, int map_flags); 9 - int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags); 10 - int bpf_lookup_elem(int fd, void *key, void *value); 11 - int bpf_delete_elem(int fd, void *key); 12 - int bpf_get_next_key(int fd, void *key, void *next_key); 13 - 14 - int bpf_prog_load(enum bpf_prog_type prog_type, 15 - const struct bpf_insn *insns, int insn_len, 16 - const char *license, int kern_version); 17 - 18 - int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type); 19 - int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type); 20 - 21 - int bpf_obj_pin(int fd, const char *pathname); 22 - int bpf_obj_get(const char *pathname); 23 - 24 - #define LOG_BUF_SIZE (256 * 1024) 25 - extern char bpf_log_buf[LOG_BUF_SIZE]; 26 8 27 9 /* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */ 28 10 ··· 185 203 .off = 0, \ 186 204 .imm = 0 }) 187 205 188 - /* create RAW socket and bind to interface 'name' */ 189 - int open_raw_sock(const char *name); 190 - 191 - struct perf_event_attr; 192 - int perf_event_open(struct perf_event_attr *attr, int pid, int cpu, 193 - int group_fd, unsigned long flags); 194 206 #endif
+4 -2
samples/bpf/lwt_len_hist_user.c
··· 14 14 #define MAX_INDEX 64 15 15 #define MAX_STARS 38 16 16 17 + char bpf_log_buf[BPF_LOG_BUF_SIZE]; 18 + 17 19 static void stars(char *str, long val, long max, int width) 18 20 { 19 21 int i; ··· 43 41 return -1; 44 42 } 45 43 46 - while (bpf_get_next_key(map_fd, &key, &next_key) == 0) { 44 + while (bpf_map_get_next_key(map_fd, &key, &next_key) == 0) { 47 45 if (next_key >= MAX_INDEX) { 48 46 fprintf(stderr, "Key %lu out of bounds\n", next_key); 49 47 continue; 50 48 } 51 49 52 - bpf_lookup_elem(map_fd, &next_key, values); 50 + bpf_map_lookup_elem(map_fd, &next_key, values); 53 51 54 52 sum = 0; 55 53 for (i = 0; i < nr_cpus; i++)
+4 -4
samples/bpf/offwaketime_user.c
··· 49 49 int i; 50 50 51 51 printf("%s;", key->target); 52 - if (bpf_lookup_elem(map_fd[3], &key->tret, ip) != 0) { 52 + if (bpf_map_lookup_elem(map_fd[3], &key->tret, ip) != 0) { 53 53 printf("---;"); 54 54 } else { 55 55 for (i = PERF_MAX_STACK_DEPTH - 1; i >= 0; i--) 56 56 print_ksym(ip[i]); 57 57 } 58 58 printf("-;"); 59 - if (bpf_lookup_elem(map_fd[3], &key->wret, ip) != 0) { 59 + if (bpf_map_lookup_elem(map_fd[3], &key->wret, ip) != 0) { 60 60 printf("---;"); 61 61 } else { 62 62 for (i = 0; i < PERF_MAX_STACK_DEPTH; i++) ··· 77 77 struct key_t key = {}, next_key; 78 78 __u64 value; 79 79 80 - while (bpf_get_next_key(fd, &key, &next_key) == 0) { 81 - bpf_lookup_elem(fd, &next_key, &value); 80 + while (bpf_map_get_next_key(fd, &key, &next_key) == 0) { 81 + bpf_map_lookup_elem(fd, &next_key, &value); 82 82 print_stack(&next_key, value); 83 83 key = next_key; 84 84 }
+4 -3
samples/bpf/sampleip_user.c
··· 21 21 #include <sys/ioctl.h> 22 22 #include "libbpf.h" 23 23 #include "bpf_load.h" 24 + #include "perf-sys.h" 24 25 25 26 #define DEFAULT_FREQ 99 26 27 #define DEFAULT_SECS 5 ··· 50 49 }; 51 50 52 51 for (i = 0; i < nr_cpus; i++) { 53 - pmu_fd[i] = perf_event_open(&pe_sample_attr, -1 /* pid */, i, 52 + pmu_fd[i] = sys_perf_event_open(&pe_sample_attr, -1 /* pid */, i, 54 53 -1 /* group_fd */, 0 /* flags */); 55 54 if (pmu_fd[i] < 0) { 56 55 fprintf(stderr, "ERROR: Initializing perf sampling\n"); ··· 96 95 97 96 /* fetch IPs and counts */ 98 97 key = 0, i = 0; 99 - while (bpf_get_next_key(fd, &key, &next_key) == 0) { 100 - bpf_lookup_elem(fd, &next_key, &value); 98 + while (bpf_map_get_next_key(fd, &key, &next_key) == 0) { 99 + bpf_map_lookup_elem(fd, &next_key, &value); 101 100 counts[i].ip = next_key; 102 101 counts[i++].count = value; 103 102 key = next_key;
+9 -5
samples/bpf/sock_example.c
··· 27 27 #include <linux/ip.h> 28 28 #include <stddef.h> 29 29 #include "libbpf.h" 30 + #include "sock_example.h" 31 + 32 + char bpf_log_buf[BPF_LOG_BUF_SIZE]; 30 33 31 34 static int test_sock(void) 32 35 { ··· 57 54 BPF_MOV64_IMM(BPF_REG_0, 0), /* r0 = 0 */ 58 55 BPF_EXIT_INSN(), 59 56 }; 57 + size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn); 60 58 61 - prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog, sizeof(prog), 62 - "GPL", 0); 59 + prog_fd = bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, prog, insns_cnt, 60 + "GPL", 0, bpf_log_buf, BPF_LOG_BUF_SIZE); 63 61 if (prog_fd < 0) { 64 62 printf("failed to load prog '%s'\n", strerror(errno)); 65 63 goto cleanup; ··· 76 72 77 73 for (i = 0; i < 10; i++) { 78 74 key = IPPROTO_TCP; 79 - assert(bpf_lookup_elem(map_fd, &key, &tcp_cnt) == 0); 75 + assert(bpf_map_lookup_elem(map_fd, &key, &tcp_cnt) == 0); 80 76 81 77 key = IPPROTO_UDP; 82 - assert(bpf_lookup_elem(map_fd, &key, &udp_cnt) == 0); 78 + assert(bpf_map_lookup_elem(map_fd, &key, &udp_cnt) == 0); 83 79 84 80 key = IPPROTO_ICMP; 85 - assert(bpf_lookup_elem(map_fd, &key, &icmp_cnt) == 0); 81 + assert(bpf_map_lookup_elem(map_fd, &key, &icmp_cnt) == 0); 86 82 87 83 printf("TCP %lld UDP %lld ICMP %lld packets\n", 88 84 tcp_cnt, udp_cnt, icmp_cnt);
+35
samples/bpf/sock_example.h
··· 1 + #include <stdlib.h> 2 + #include <stdio.h> 3 + #include <linux/unistd.h> 4 + #include <unistd.h> 5 + #include <string.h> 6 + #include <errno.h> 7 + #include <net/ethernet.h> 8 + #include <net/if.h> 9 + #include <linux/if_packet.h> 10 + #include <arpa/inet.h> 11 + #include "libbpf.h" 12 + 13 + static inline int open_raw_sock(const char *name) 14 + { 15 + struct sockaddr_ll sll; 16 + int sock; 17 + 18 + sock = socket(PF_PACKET, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, htons(ETH_P_ALL)); 19 + if (sock < 0) { 20 + printf("cannot create raw socket\n"); 21 + return -1; 22 + } 23 + 24 + memset(&sll, 0, sizeof(sll)); 25 + sll.sll_family = AF_PACKET; 26 + sll.sll_ifindex = if_nametoindex(name); 27 + sll.sll_protocol = htons(ETH_P_ALL); 28 + if (bind(sock, (struct sockaddr *)&sll, sizeof(sll)) < 0) { 29 + printf("bind to %s: %s\n", name, strerror(errno)); 30 + close(sock); 31 + return -1; 32 + } 33 + 34 + return sock; 35 + }
+4 -3
samples/bpf/sockex1_user.c
··· 3 3 #include <linux/bpf.h> 4 4 #include "libbpf.h" 5 5 #include "bpf_load.h" 6 + #include "sock_example.h" 6 7 #include <unistd.h> 7 8 #include <arpa/inet.h> 8 9 ··· 33 32 int key; 34 33 35 34 key = IPPROTO_TCP; 36 - assert(bpf_lookup_elem(map_fd[0], &key, &tcp_cnt) == 0); 35 + assert(bpf_map_lookup_elem(map_fd[0], &key, &tcp_cnt) == 0); 37 36 38 37 key = IPPROTO_UDP; 39 - assert(bpf_lookup_elem(map_fd[0], &key, &udp_cnt) == 0); 38 + assert(bpf_map_lookup_elem(map_fd[0], &key, &udp_cnt) == 0); 40 39 41 40 key = IPPROTO_ICMP; 42 - assert(bpf_lookup_elem(map_fd[0], &key, &icmp_cnt) == 0); 41 + assert(bpf_map_lookup_elem(map_fd[0], &key, &icmp_cnt) == 0); 43 42 44 43 printf("TCP %lld UDP %lld ICMP %lld bytes\n", 45 44 tcp_cnt, udp_cnt, icmp_cnt);
+3 -2
samples/bpf/sockex2_user.c
··· 3 3 #include <linux/bpf.h> 4 4 #include "libbpf.h" 5 5 #include "bpf_load.h" 6 + #include "sock_example.h" 6 7 #include <unistd.h> 7 8 #include <arpa/inet.h> 8 9 #include <sys/resource.h> ··· 40 39 int key = 0, next_key; 41 40 struct pair value; 42 41 43 - while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) { 44 - bpf_lookup_elem(map_fd[0], &next_key, &value); 42 + while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0) { 43 + bpf_map_lookup_elem(map_fd[0], &next_key, &value); 45 44 printf("ip %s bytes %lld packets %lld\n", 46 45 inet_ntoa((struct in_addr){htonl(next_key)}), 47 46 value.bytes, value.packets);
+3 -2
samples/bpf/sockex3_user.c
··· 3 3 #include <linux/bpf.h> 4 4 #include "libbpf.h" 5 5 #include "bpf_load.h" 6 + #include "sock_example.h" 6 7 #include <unistd.h> 7 8 #include <arpa/inet.h> 8 9 #include <sys/resource.h> ··· 55 54 56 55 sleep(1); 57 56 printf("IP src.port -> dst.port bytes packets\n"); 58 - while (bpf_get_next_key(map_fd[2], &key, &next_key) == 0) { 59 - bpf_lookup_elem(map_fd[2], &next_key, &value); 57 + while (bpf_map_get_next_key(map_fd[2], &key, &next_key) == 0) { 58 + bpf_map_lookup_elem(map_fd[2], &next_key, &value); 60 59 printf("%s.%05d -> %s.%05d %12lld %12lld\n", 61 60 inet_ntoa((struct in_addr){htonl(next_key.src)}), 62 61 next_key.port16[0],
+4 -4
samples/bpf/spintest_user.c
··· 31 31 for (i = 0; i < 5; i++) { 32 32 key = 0; 33 33 printf("kprobing funcs:"); 34 - while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) { 35 - bpf_lookup_elem(map_fd[0], &next_key, &value); 34 + while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0) { 35 + bpf_map_lookup_elem(map_fd[0], &next_key, &value); 36 36 assert(next_key == value); 37 37 sym = ksym_search(value); 38 38 printf(" %s", sym->name); ··· 41 41 if (key) 42 42 printf("\n"); 43 43 key = 0; 44 - while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) 45 - bpf_delete_elem(map_fd[0], &next_key); 44 + while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0) 45 + bpf_map_delete_elem(map_fd[0], &next_key); 46 46 sleep(1); 47 47 } 48 48
+2 -2
samples/bpf/tc_l2_redirect_user.c
··· 60 60 } 61 61 62 62 /* bpf_tunnel_key.remote_ipv4 expects host byte orders */ 63 - ret = bpf_update_elem(array_fd, &array_key, &ifindex, 0); 63 + ret = bpf_map_update_elem(array_fd, &array_key, &ifindex, 0); 64 64 if (ret) { 65 - perror("bpf_update_elem"); 65 + perror("bpf_map_update_elem"); 66 66 goto out; 67 67 } 68 68
+2 -2
samples/bpf/test_cgrp2_array_pin.c
··· 85 85 } 86 86 } 87 87 88 - ret = bpf_update_elem(array_fd, &array_key, &cg2_fd, 0); 88 + ret = bpf_map_update_elem(array_fd, &array_key, &cg2_fd, 0); 89 89 if (ret) { 90 - perror("bpf_update_elem"); 90 + perror("bpf_map_update_elem"); 91 91 goto out; 92 92 } 93 93
+8 -4
samples/bpf/test_cgrp2_attach.c
··· 36 36 MAP_KEY_BYTES, 37 37 }; 38 38 39 + char bpf_log_buf[BPF_LOG_BUF_SIZE]; 40 + 39 41 static int prog_load(int map_fd, int verdict) 40 42 { 41 43 struct bpf_insn prog[] = { ··· 68 66 BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */ 69 67 BPF_EXIT_INSN(), 70 68 }; 69 + size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn); 71 70 72 - return bpf_prog_load(BPF_PROG_TYPE_CGROUP_SKB, 73 - prog, sizeof(prog), "GPL", 0); 71 + return bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB, 72 + prog, insns_cnt, "GPL", 0, 73 + bpf_log_buf, BPF_LOG_BUF_SIZE); 74 74 } 75 75 76 76 static int usage(const char *argv0) ··· 112 108 } 113 109 while (1) { 114 110 key = MAP_KEY_PACKETS; 115 - assert(bpf_lookup_elem(map_fd, &key, &pkt_cnt) == 0); 111 + assert(bpf_map_lookup_elem(map_fd, &key, &pkt_cnt) == 0); 116 112 117 113 key = MAP_KEY_BYTES; 118 - assert(bpf_lookup_elem(map_fd, &key, &byte_cnt) == 0); 114 + assert(bpf_map_lookup_elem(map_fd, &key, &byte_cnt) == 0); 119 115 120 116 printf("cgroup received %lld packets, %lld bytes\n", 121 117 pkt_cnt, byte_cnt);
+6 -2
samples/bpf/test_cgrp2_attach2.c
··· 32 32 #define BAR "/foo/bar/" 33 33 #define PING_CMD "ping -c1 -w1 127.0.0.1" 34 34 35 + char bpf_log_buf[BPF_LOG_BUF_SIZE]; 36 + 35 37 static int prog_load(int verdict) 36 38 { 37 39 int ret; ··· 41 39 BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */ 42 40 BPF_EXIT_INSN(), 43 41 }; 42 + size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn); 44 43 45 - ret = bpf_prog_load(BPF_PROG_TYPE_CGROUP_SKB, 46 - prog, sizeof(prog), "GPL", 0); 44 + ret = bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB, 45 + prog, insns_cnt, "GPL", 0, 46 + bpf_log_buf, BPF_LOG_BUF_SIZE); 47 47 48 48 if (ret < 0) { 49 49 log_err("Loading program");
+5 -2
samples/bpf/test_cgrp2_sock.c
··· 23 23 24 24 #include "libbpf.h" 25 25 26 + char bpf_log_buf[BPF_LOG_BUF_SIZE]; 27 + 26 28 static int prog_load(int idx) 27 29 { 28 30 struct bpf_insn prog[] = { ··· 35 33 BPF_MOV64_IMM(BPF_REG_0, 1), /* r0 = verdict */ 36 34 BPF_EXIT_INSN(), 37 35 }; 36 + size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn); 38 37 39 - return bpf_prog_load(BPF_PROG_TYPE_CGROUP_SOCK, prog, sizeof(prog), 40 - "GPL", 0); 38 + return bpf_load_program(BPF_PROG_TYPE_CGROUP_SOCK, prog, insns_cnt, 39 + "GPL", 0, bpf_log_buf, BPF_LOG_BUF_SIZE); 41 40 } 42 41 43 42 static int usage(const char *argv0)
+4 -4
samples/bpf/test_current_task_under_cgroup_user.c
··· 36 36 if (!cg2) 37 37 goto err; 38 38 39 - if (bpf_update_elem(map_fd[0], &idx, &cg2, BPF_ANY)) { 39 + if (bpf_map_update_elem(map_fd[0], &idx, &cg2, BPF_ANY)) { 40 40 log_err("Adding target cgroup to map"); 41 41 goto err; 42 42 } ··· 50 50 */ 51 51 52 52 sync(); 53 - bpf_lookup_elem(map_fd[1], &idx, &remote_pid); 53 + bpf_map_lookup_elem(map_fd[1], &idx, &remote_pid); 54 54 55 55 if (local_pid != remote_pid) { 56 56 fprintf(stderr, ··· 64 64 goto err; 65 65 66 66 remote_pid = 0; 67 - bpf_update_elem(map_fd[1], &idx, &remote_pid, BPF_ANY); 67 + bpf_map_update_elem(map_fd[1], &idx, &remote_pid, BPF_ANY); 68 68 69 69 sync(); 70 - bpf_lookup_elem(map_fd[1], &idx, &remote_pid); 70 + bpf_map_lookup_elem(map_fd[1], &idx, &remote_pid); 71 71 72 72 if (local_pid == remote_pid) { 73 73 fprintf(stderr, "BPF cgroup negative test did not work\n");
+16 -16
samples/bpf/test_lru_dist.c
··· 134 134 int seen = 0; 135 135 136 136 lru->total++; 137 - if (!bpf_lookup_elem(lru->map_fd, &key, &node)) { 137 + if (!bpf_map_lookup_elem(lru->map_fd, &key, &node)) { 138 138 if (node) { 139 139 list_move(&node->list, &lru->list); 140 140 return 1; ··· 151 151 node = list_last_entry(&lru->list, 152 152 struct pfect_lru_node, 153 153 list); 154 - bpf_update_elem(lru->map_fd, &node->key, &null_node, BPF_EXIST); 154 + bpf_map_update_elem(lru->map_fd, &node->key, &null_node, BPF_EXIST); 155 155 } 156 156 157 157 node->key = key; ··· 159 159 160 160 lru->nr_misses++; 161 161 if (seen) { 162 - assert(!bpf_update_elem(lru->map_fd, &key, &node, BPF_EXIST)); 162 + assert(!bpf_map_update_elem(lru->map_fd, &key, &node, BPF_EXIST)); 163 163 } else { 164 164 lru->nr_unique++; 165 - assert(!bpf_update_elem(lru->map_fd, &key, &node, BPF_NOEXIST)); 165 + assert(!bpf_map_update_elem(lru->map_fd, &key, &node, BPF_NOEXIST)); 166 166 } 167 167 168 168 return seen; ··· 285 285 286 286 pfect_lru_lookup_or_insert(&pfect_lru, key); 287 287 288 - if (!bpf_lookup_elem(lru_map_fd, &key, &value)) 288 + if (!bpf_map_lookup_elem(lru_map_fd, &key, &value)) 289 289 continue; 290 290 291 - if (bpf_update_elem(lru_map_fd, &key, &value, BPF_NOEXIST)) { 292 - printf("bpf_update_elem(lru_map_fd, %llu): errno:%d\n", 291 + if (bpf_map_update_elem(lru_map_fd, &key, &value, BPF_NOEXIST)) { 292 + printf("bpf_map_update_elem(lru_map_fd, %llu): errno:%d\n", 293 293 key, errno); 294 294 assert(0); 295 295 } ··· 358 358 for (key = 1; key <= 1000; key++) { 359 359 int start_key, end_key; 360 360 361 - assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == 0); 361 + assert(bpf_map_update_elem(map_fd, &key, value, BPF_NOEXIST) == 0); 362 362 363 363 start_key = 101; 364 364 end_key = min(key, 900); 365 365 366 366 while (start_key <= end_key) { 367 - bpf_lookup_elem(map_fd, &start_key, value); 367 + bpf_map_lookup_elem(map_fd, &start_key, value); 368 368 start_key++; 369 369 } 370 370 } 371 371 372 372 for (key = 1; key <= 1000; key++) { 373 - if (bpf_lookup_elem(map_fd, &key, value)) { 373 + if (bpf_map_lookup_elem(map_fd, &key, value)) { 374 374 if (key <= 100) 375 375 old_unused_losses++; 376 376 else if (key <= 900) ··· 408 408 value[0] = 1234; 409 409 410 410 for (key = 1; key <= 1000; key++) 411 - assert(!bpf_update_elem(map_fd, &key, value, BPF_NOEXIST)); 411 + assert(!bpf_map_update_elem(map_fd, &key, value, BPF_NOEXIST)); 412 412 413 413 for (key = 1; key <= 1000; key++) { 414 - if (bpf_lookup_elem(map_fd, &key, value)) 414 + if (bpf_map_lookup_elem(map_fd, &key, value)) 415 415 nr_losses++; 416 416 } 417 417 ··· 436 436 next_ins_key = stable_base; 437 437 value[0] = 1234; 438 438 for (i = 0; i < nr_stable_elems; i++) { 439 - assert(bpf_update_elem(map_fd, &next_ins_key, value, 439 + assert(bpf_map_update_elem(map_fd, &next_ins_key, value, 440 440 BPF_NOEXIST) == 0); 441 441 next_ins_key++; 442 442 } ··· 448 448 449 449 if (rn % 10) { 450 450 key = rn % nr_stable_elems + stable_base; 451 - bpf_lookup_elem(map_fd, &key, value); 451 + bpf_map_lookup_elem(map_fd, &key, value); 452 452 } else { 453 - bpf_update_elem(map_fd, &next_ins_key, value, 453 + bpf_map_update_elem(map_fd, &next_ins_key, value, 454 454 BPF_NOEXIST); 455 455 next_ins_key++; 456 456 } ··· 458 458 459 459 key = stable_base; 460 460 for (i = 0; i < nr_stable_elems; i++) { 461 - if (bpf_lookup_elem(map_fd, &key, value)) 461 + if (bpf_map_lookup_elem(map_fd, &key, value)) 462 462 nr_losses++; 463 463 key++; 464 464 }
+1 -1
samples/bpf/test_probe_write_user_user.c
··· 50 50 mapped_addr_in->sin_port = htons(5555); 51 51 mapped_addr_in->sin_addr.s_addr = inet_addr("255.255.255.255"); 52 52 53 - assert(!bpf_update_elem(map_fd[0], &mapped_addr, &serv_addr, BPF_ANY)); 53 + assert(!bpf_map_update_elem(map_fd[0], &mapped_addr, &serv_addr, BPF_ANY)); 54 54 55 55 assert(listen(serverfd, 5) == 0); 56 56
+12 -11
samples/bpf/trace_event_user.c
··· 20 20 #include <sys/resource.h> 21 21 #include "libbpf.h" 22 22 #include "bpf_load.h" 23 + #include "perf-sys.h" 23 24 24 25 #define SAMPLE_FREQ 50 25 26 ··· 62 61 int i; 63 62 64 63 printf("%3lld %s;", count, key->comm); 65 - if (bpf_lookup_elem(map_fd[1], &key->kernstack, ip) != 0) { 64 + if (bpf_map_lookup_elem(map_fd[1], &key->kernstack, ip) != 0) { 66 65 printf("---;"); 67 66 } else { 68 67 for (i = PERF_MAX_STACK_DEPTH - 1; i >= 0; i--) 69 68 print_ksym(ip[i]); 70 69 } 71 70 printf("-;"); 72 - if (bpf_lookup_elem(map_fd[1], &key->userstack, ip) != 0) { 71 + if (bpf_map_lookup_elem(map_fd[1], &key->userstack, ip) != 0) { 73 72 printf("---;"); 74 73 } else { 75 74 for (i = PERF_MAX_STACK_DEPTH - 1; i >= 0; i--) ··· 99 98 int fd = map_fd[0], stack_map = map_fd[1]; 100 99 101 100 sys_read_seen = sys_write_seen = false; 102 - while (bpf_get_next_key(fd, &key, &next_key) == 0) { 103 - bpf_lookup_elem(fd, &next_key, &value); 101 + while (bpf_map_get_next_key(fd, &key, &next_key) == 0) { 102 + bpf_map_lookup_elem(fd, &next_key, &value); 104 103 print_stack(&next_key, value); 105 - bpf_delete_elem(fd, &next_key); 104 + bpf_map_delete_elem(fd, &next_key); 106 105 key = next_key; 107 106 } 108 107 ··· 112 111 } 113 112 114 113 /* clear stack map */ 115 - while (bpf_get_next_key(stack_map, &stackid, &next_id) == 0) { 116 - bpf_delete_elem(stack_map, &next_id); 114 + while (bpf_map_get_next_key(stack_map, &stackid, &next_id) == 0) { 115 + bpf_map_delete_elem(stack_map, &next_id); 117 116 stackid = next_id; 118 117 } 119 118 } ··· 126 125 127 126 /* open perf_event on all cpus */ 128 127 for (i = 0; i < nr_cpus; i++) { 129 - pmu_fd[i] = perf_event_open(attr, -1, i, -1, 0); 128 + pmu_fd[i] = sys_perf_event_open(attr, -1, i, -1, 0); 130 129 if (pmu_fd[i] < 0) { 131 - printf("perf_event_open failed\n"); 130 + printf("sys_perf_event_open failed\n"); 132 131 goto all_cpu_err; 133 132 } 134 133 assert(ioctl(pmu_fd[i], PERF_EVENT_IOC_SET_BPF, prog_fd[0]) == 0); ··· 147 146 int pmu_fd; 148 147 149 148 /* open task bound event */ 150 - pmu_fd = perf_event_open(attr, 0, -1, -1, 0); 149 + pmu_fd = sys_perf_event_open(attr, 0, -1, -1, 0); 151 150 if (pmu_fd < 0) { 152 - printf("perf_event_open failed\n"); 151 + printf("sys_perf_event_open failed\n"); 153 152 return; 154 153 } 155 154 assert(ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd[0]) == 0);
+4 -3
samples/bpf/trace_output_user.c
··· 21 21 #include <signal.h> 22 22 #include "libbpf.h" 23 23 #include "bpf_load.h" 24 + #include "perf-sys.h" 24 25 25 26 static int pmu_fd; 26 27 ··· 62 61 char data[]; 63 62 }; 64 63 65 - void perf_event_read(print_fn fn) 64 + static void perf_event_read(print_fn fn) 66 65 { 67 66 __u64 data_tail = header->data_tail; 68 67 __u64 data_head = header->data_head; ··· 160 159 }; 161 160 int key = 0; 162 161 163 - pmu_fd = perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0); 162 + pmu_fd = sys_perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0); 164 163 165 164 assert(pmu_fd >= 0); 166 - assert(bpf_update_elem(map_fd[0], &key, &pmu_fd, BPF_ANY) == 0); 165 + assert(bpf_map_update_elem(map_fd[0], &key, &pmu_fd, BPF_ANY) == 0); 167 166 ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0); 168 167 } 169 168
+5 -5
samples/bpf/tracex2_user.c
··· 48 48 long max_value = 0; 49 49 int i, ind; 50 50 51 - while (bpf_get_next_key(fd, &key, &next_key) == 0) { 51 + while (bpf_map_get_next_key(fd, &key, &next_key) == 0) { 52 52 if (memcmp(&next_key, task, SIZE)) { 53 53 key = next_key; 54 54 continue; 55 55 } 56 - bpf_lookup_elem(fd, &next_key, values); 56 + bpf_map_lookup_elem(fd, &next_key, values); 57 57 value = 0; 58 58 for (i = 0; i < nr_cpus; i++) 59 59 value += values[i]; ··· 83 83 int task_cnt = 0; 84 84 int i; 85 85 86 - while (bpf_get_next_key(fd, &key, &next_key) == 0) { 86 + while (bpf_map_get_next_key(fd, &key, &next_key) == 0) { 87 87 int found = 0; 88 88 89 89 for (i = 0; i < task_cnt; i++) ··· 136 136 137 137 for (i = 0; i < 5; i++) { 138 138 key = 0; 139 - while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) { 140 - bpf_lookup_elem(map_fd[0], &next_key, &value); 139 + while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0) { 140 + bpf_map_lookup_elem(map_fd[0], &next_key, &value); 141 141 printf("location 0x%lx count %ld\n", next_key, value); 142 142 key = next_key; 143 143 }
+2 -2
samples/bpf/tracex3_user.c
··· 28 28 29 29 memset(values, 0, sizeof(values)); 30 30 for (key = 0; key < SLOTS; key++) 31 - bpf_update_elem(fd, &key, values, BPF_ANY); 31 + bpf_map_update_elem(fd, &key, values, BPF_ANY); 32 32 } 33 33 34 34 const char *color[] = { ··· 89 89 int i; 90 90 91 91 for (key = 0; key < SLOTS; key++) { 92 - bpf_lookup_elem(fd, &key, values); 92 + bpf_map_lookup_elem(fd, &key, values); 93 93 value = 0; 94 94 for (i = 0; i < nr_cpus; i++) 95 95 value += values[i];
+2 -2
samples/bpf/tracex4_user.c
··· 37 37 key = write(1, "\e[1;1H\e[2J", 12); /* clear screen */ 38 38 39 39 key = -1; 40 - while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) { 41 - bpf_lookup_elem(map_fd[0], &next_key, &v); 40 + while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0) { 41 + bpf_map_lookup_elem(map_fd[0], &next_key, &v); 42 42 key = next_key; 43 43 if (val - v.val < 1000000000ll) 44 44 /* object was allocated more then 1 sec ago */
+3 -2
samples/bpf/tracex6_user.c
··· 10 10 #include <linux/bpf.h> 11 11 #include "libbpf.h" 12 12 #include "bpf_load.h" 13 + #include "perf-sys.h" 13 14 14 15 #define SAMPLE_PERIOD 0x7fffffffffffffffULL 15 16 ··· 31 30 }; 32 31 33 32 for (i = 0; i < nr_cpus; i++) { 34 - pmu_fd[i] = perf_event_open(&attr_insn_pmu, -1/*pid*/, i/*cpu*/, -1/*group_fd*/, 0); 33 + pmu_fd[i] = sys_perf_event_open(&attr_insn_pmu, -1/*pid*/, i/*cpu*/, -1/*group_fd*/, 0); 35 34 if (pmu_fd[i] < 0) { 36 35 printf("event syscall failed\n"); 37 36 goto exit; 38 37 } 39 38 40 - bpf_update_elem(map_fd[0], &i, &pmu_fd[i], BPF_ANY); 39 + bpf_map_update_elem(map_fd[0], &i, &pmu_fd[i], BPF_ANY); 41 40 ioctl(pmu_fd[i], PERF_EVENT_IOC_ENABLE, 0); 42 41 } 43 42
+1 -1
samples/bpf/xdp1_user.c
··· 43 43 for (key = 0; key < nr_keys; key++) { 44 44 __u64 sum = 0; 45 45 46 - assert(bpf_lookup_elem(map_fd[0], &key, values) == 0); 46 + assert(bpf_map_lookup_elem(map_fd[0], &key, values) == 0); 47 47 for (i = 0; i < nr_cpus; i++) 48 48 sum += (values[i] - prev[key][i]); 49 49 if (sum)
+3 -3
samples/bpf/xdp_tx_iptunnel_user.c
··· 51 51 for (proto = 0; proto < nr_protos; proto++) { 52 52 __u64 sum = 0; 53 53 54 - assert(bpf_lookup_elem(map_fd[0], &proto, values) == 0); 54 + assert(bpf_map_lookup_elem(map_fd[0], &proto, values) == 0); 55 55 for (i = 0; i < nr_cpus; i++) 56 56 sum += (values[i] - prev[proto][i]); 57 57 ··· 237 237 238 238 while (min_port <= max_port) { 239 239 vip.dport = htons(min_port++); 240 - if (bpf_update_elem(map_fd[1], &vip, &tnl, BPF_NOEXIST)) { 241 - perror("bpf_update_elem(&vip2tnl)"); 240 + if (bpf_map_update_elem(map_fd[1], &vip, &tnl, BPF_NOEXIST)) { 241 + perror("bpf_map_update_elem(&vip2tnl)"); 242 242 return 1; 243 243 } 244 244 }
+364 -229
tools/include/uapi/linux/bpf.h
··· 73 73 BPF_PROG_LOAD, 74 74 BPF_OBJ_PIN, 75 75 BPF_OBJ_GET, 76 + BPF_PROG_ATTACH, 77 + BPF_PROG_DETACH, 76 78 }; 77 79 78 80 enum bpf_map_type { ··· 87 85 BPF_MAP_TYPE_PERCPU_ARRAY, 88 86 BPF_MAP_TYPE_STACK_TRACE, 89 87 BPF_MAP_TYPE_CGROUP_ARRAY, 88 + BPF_MAP_TYPE_LRU_HASH, 89 + BPF_MAP_TYPE_LRU_PERCPU_HASH, 90 90 }; 91 91 92 92 enum bpf_prog_type { ··· 99 95 BPF_PROG_TYPE_SCHED_ACT, 100 96 BPF_PROG_TYPE_TRACEPOINT, 101 97 BPF_PROG_TYPE_XDP, 98 + BPF_PROG_TYPE_PERF_EVENT, 99 + BPF_PROG_TYPE_CGROUP_SKB, 100 + BPF_PROG_TYPE_CGROUP_SOCK, 101 + BPF_PROG_TYPE_LWT_IN, 102 + BPF_PROG_TYPE_LWT_OUT, 103 + BPF_PROG_TYPE_LWT_XMIT, 102 104 }; 105 + 106 + enum bpf_attach_type { 107 + BPF_CGROUP_INET_INGRESS, 108 + BPF_CGROUP_INET_EGRESS, 109 + BPF_CGROUP_INET_SOCK_CREATE, 110 + __MAX_BPF_ATTACH_TYPE 111 + }; 112 + 113 + #define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE 103 114 104 115 #define BPF_PSEUDO_MAP_FD 1 105 116 ··· 124 105 #define BPF_EXIST 2 /* update existing element */ 125 106 126 107 #define BPF_F_NO_PREALLOC (1U << 0) 108 + /* Instead of having one common LRU list in the 109 + * BPF_MAP_TYPE_LRU_[PERCPU_]HASH map, use a percpu LRU list 110 + * which can scale and perform better. 111 + * Note, the LRU nodes (including free nodes) cannot be moved 112 + * across different LRU lists. 113 + */ 114 + #define BPF_F_NO_COMMON_LRU (1U << 1) 127 115 128 116 union bpf_attr { 129 117 struct { /* anonymous struct used by BPF_MAP_CREATE command */ ··· 166 140 __aligned_u64 pathname; 167 141 __u32 bpf_fd; 168 142 }; 143 + 144 + struct { /* anonymous struct used by BPF_PROG_ATTACH/DETACH commands */ 145 + __u32 target_fd; /* container object to attach to */ 146 + __u32 attach_bpf_fd; /* eBPF program to attach */ 147 + __u32 attach_type; 148 + }; 169 149 } __attribute__((aligned(8))); 150 + 151 + /* BPF helper function descriptions: 152 + * 153 + * void *bpf_map_lookup_elem(&map, &key) 154 + * Return: Map value or NULL 155 + * 156 + * int bpf_map_update_elem(&map, &key, &value, flags) 157 + * Return: 0 on success or negative error 158 + * 159 + * int bpf_map_delete_elem(&map, &key) 160 + * Return: 0 on success or negative error 161 + * 162 + * int bpf_probe_read(void *dst, int size, void *src) 163 + * Return: 0 on success or negative error 164 + * 165 + * u64 bpf_ktime_get_ns(void) 166 + * Return: current ktime 167 + * 168 + * int bpf_trace_printk(const char *fmt, int fmt_size, ...) 169 + * Return: length of buffer written or negative error 170 + * 171 + * u32 bpf_prandom_u32(void) 172 + * Return: random value 173 + * 174 + * u32 bpf_raw_smp_processor_id(void) 175 + * Return: SMP processor ID 176 + * 177 + * int bpf_skb_store_bytes(skb, offset, from, len, flags) 178 + * store bytes into packet 179 + * @skb: pointer to skb 180 + * @offset: offset within packet from skb->mac_header 181 + * @from: pointer where to copy bytes from 182 + * @len: number of bytes to store into packet 183 + * @flags: bit 0 - if true, recompute skb->csum 184 + * other bits - reserved 185 + * Return: 0 on success or negative error 186 + * 187 + * int bpf_l3_csum_replace(skb, offset, from, to, flags) 188 + * recompute IP checksum 189 + * @skb: pointer to skb 190 + * @offset: offset within packet where IP checksum is located 191 + * @from: old value of header field 192 + * @to: new value of header field 193 + * @flags: bits 0-3 - size of header field 194 + * other bits - reserved 195 + * Return: 0 on success or negative error 196 + * 197 + * int bpf_l4_csum_replace(skb, offset, from, to, flags) 198 + * recompute TCP/UDP checksum 199 + * @skb: pointer to skb 200 + * @offset: offset within packet where TCP/UDP checksum is located 201 + * @from: old value of header field 202 + * @to: new value of header field 203 + * @flags: bits 0-3 - size of header field 204 + * bit 4 - is pseudo header 205 + * other bits - reserved 206 + * Return: 0 on success or negative error 207 + * 208 + * int bpf_tail_call(ctx, prog_array_map, index) 209 + * jump into another BPF program 210 + * @ctx: context pointer passed to next program 211 + * @prog_array_map: pointer to map which type is BPF_MAP_TYPE_PROG_ARRAY 212 + * @index: index inside array that selects specific program to run 213 + * Return: 0 on success or negative error 214 + * 215 + * int bpf_clone_redirect(skb, ifindex, flags) 216 + * redirect to another netdev 217 + * @skb: pointer to skb 218 + * @ifindex: ifindex of the net device 219 + * @flags: bit 0 - if set, redirect to ingress instead of egress 220 + * other bits - reserved 221 + * Return: 0 on success or negative error 222 + * 223 + * u64 bpf_get_current_pid_tgid(void) 224 + * Return: current->tgid << 32 | current->pid 225 + * 226 + * u64 bpf_get_current_uid_gid(void) 227 + * Return: current_gid << 32 | current_uid 228 + * 229 + * int bpf_get_current_comm(char *buf, int size_of_buf) 230 + * stores current->comm into buf 231 + * Return: 0 on success or negative error 232 + * 233 + * u32 bpf_get_cgroup_classid(skb) 234 + * retrieve a proc's classid 235 + * @skb: pointer to skb 236 + * Return: classid if != 0 237 + * 238 + * int bpf_skb_vlan_push(skb, vlan_proto, vlan_tci) 239 + * Return: 0 on success or negative error 240 + * 241 + * int bpf_skb_vlan_pop(skb) 242 + * Return: 0 on success or negative error 243 + * 244 + * int bpf_skb_get_tunnel_key(skb, key, size, flags) 245 + * int bpf_skb_set_tunnel_key(skb, key, size, flags) 246 + * retrieve or populate tunnel metadata 247 + * @skb: pointer to skb 248 + * @key: pointer to 'struct bpf_tunnel_key' 249 + * @size: size of 'struct bpf_tunnel_key' 250 + * @flags: room for future extensions 251 + * Return: 0 on success or negative error 252 + * 253 + * u64 bpf_perf_event_read(&map, index) 254 + * Return: Number events read or error code 255 + * 256 + * int bpf_redirect(ifindex, flags) 257 + * redirect to another netdev 258 + * @ifindex: ifindex of the net device 259 + * @flags: bit 0 - if set, redirect to ingress instead of egress 260 + * other bits - reserved 261 + * Return: TC_ACT_REDIRECT 262 + * 263 + * u32 bpf_get_route_realm(skb) 264 + * retrieve a dst's tclassid 265 + * @skb: pointer to skb 266 + * Return: realm if != 0 267 + * 268 + * int bpf_perf_event_output(ctx, map, index, data, size) 269 + * output perf raw sample 270 + * @ctx: struct pt_regs* 271 + * @map: pointer to perf_event_array map 272 + * @index: index of event in the map 273 + * @data: data on stack to be output as raw data 274 + * @size: size of data 275 + * Return: 0 on success or negative error 276 + * 277 + * int bpf_get_stackid(ctx, map, flags) 278 + * walk user or kernel stack and return id 279 + * @ctx: struct pt_regs* 280 + * @map: pointer to stack_trace map 281 + * @flags: bits 0-7 - numer of stack frames to skip 282 + * bit 8 - collect user stack instead of kernel 283 + * bit 9 - compare stacks by hash only 284 + * bit 10 - if two different stacks hash into the same stackid 285 + * discard old 286 + * other bits - reserved 287 + * Return: >= 0 stackid on success or negative error 288 + * 289 + * s64 bpf_csum_diff(from, from_size, to, to_size, seed) 290 + * calculate csum diff 291 + * @from: raw from buffer 292 + * @from_size: length of from buffer 293 + * @to: raw to buffer 294 + * @to_size: length of to buffer 295 + * @seed: optional seed 296 + * Return: csum result or negative error code 297 + * 298 + * int bpf_skb_get_tunnel_opt(skb, opt, size) 299 + * retrieve tunnel options metadata 300 + * @skb: pointer to skb 301 + * @opt: pointer to raw tunnel option data 302 + * @size: size of @opt 303 + * Return: option size 304 + * 305 + * int bpf_skb_set_tunnel_opt(skb, opt, size) 306 + * populate tunnel options metadata 307 + * @skb: pointer to skb 308 + * @opt: pointer to raw tunnel option data 309 + * @size: size of @opt 310 + * Return: 0 on success or negative error 311 + * 312 + * int bpf_skb_change_proto(skb, proto, flags) 313 + * Change protocol of the skb. Currently supported is v4 -> v6, 314 + * v6 -> v4 transitions. The helper will also resize the skb. eBPF 315 + * program is expected to fill the new headers via skb_store_bytes 316 + * and lX_csum_replace. 317 + * @skb: pointer to skb 318 + * @proto: new skb->protocol type 319 + * @flags: reserved 320 + * Return: 0 on success or negative error 321 + * 322 + * int bpf_skb_change_type(skb, type) 323 + * Change packet type of skb. 324 + * @skb: pointer to skb 325 + * @type: new skb->pkt_type type 326 + * Return: 0 on success or negative error 327 + * 328 + * int bpf_skb_under_cgroup(skb, map, index) 329 + * Check cgroup2 membership of skb 330 + * @skb: pointer to skb 331 + * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type 332 + * @index: index of the cgroup in the bpf_map 333 + * Return: 334 + * == 0 skb failed the cgroup2 descendant test 335 + * == 1 skb succeeded the cgroup2 descendant test 336 + * < 0 error 337 + * 338 + * u32 bpf_get_hash_recalc(skb) 339 + * Retrieve and possibly recalculate skb->hash. 340 + * @skb: pointer to skb 341 + * Return: hash 342 + * 343 + * u64 bpf_get_current_task(void) 344 + * Returns current task_struct 345 + * Return: current 346 + * 347 + * int bpf_probe_write_user(void *dst, void *src, int len) 348 + * safely attempt to write to a location 349 + * @dst: destination address in userspace 350 + * @src: source address on stack 351 + * @len: number of bytes to copy 352 + * Return: 0 on success or negative error 353 + * 354 + * int bpf_current_task_under_cgroup(map, index) 355 + * Check cgroup2 membership of current task 356 + * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type 357 + * @index: index of the cgroup in the bpf_map 358 + * Return: 359 + * == 0 current failed the cgroup2 descendant test 360 + * == 1 current succeeded the cgroup2 descendant test 361 + * < 0 error 362 + * 363 + * int bpf_skb_change_tail(skb, len, flags) 364 + * The helper will resize the skb to the given new size, to be used f.e. 365 + * with control messages. 366 + * @skb: pointer to skb 367 + * @len: new skb length 368 + * @flags: reserved 369 + * Return: 0 on success or negative error 370 + * 371 + * int bpf_skb_pull_data(skb, len) 372 + * The helper will pull in non-linear data in case the skb is non-linear 373 + * and not all of len are part of the linear section. Only needed for 374 + * read/write with direct packet access. 375 + * @skb: pointer to skb 376 + * @len: len to make read/writeable 377 + * Return: 0 on success or negative error 378 + * 379 + * s64 bpf_csum_update(skb, csum) 380 + * Adds csum into skb->csum in case of CHECKSUM_COMPLETE. 381 + * @skb: pointer to skb 382 + * @csum: csum to add 383 + * Return: csum on success or negative error 384 + * 385 + * void bpf_set_hash_invalid(skb) 386 + * Invalidate current skb->hash. 387 + * @skb: pointer to skb 388 + * 389 + * int bpf_get_numa_node_id() 390 + * Return: Id of current NUMA node. 391 + * 392 + * int bpf_skb_change_head() 393 + * Grows headroom of skb and adjusts MAC header offset accordingly. 394 + * Will extends/reallocae as required automatically. 395 + * May change skb data pointer and will thus invalidate any check 396 + * performed for direct packet access. 397 + * @skb: pointer to skb 398 + * @len: length of header to be pushed in front 399 + * @flags: Flags (unused for now) 400 + * Return: 0 on success or negative error 401 + * 402 + * int bpf_xdp_adjust_head(xdp_md, delta) 403 + * Adjust the xdp_md.data by delta 404 + * @xdp_md: pointer to xdp_md 405 + * @delta: An positive/negative integer to be added to xdp_md.data 406 + * Return: 0 on success or negative on error 407 + */ 408 + #define __BPF_FUNC_MAPPER(FN) \ 409 + FN(unspec), \ 410 + FN(map_lookup_elem), \ 411 + FN(map_update_elem), \ 412 + FN(map_delete_elem), \ 413 + FN(probe_read), \ 414 + FN(ktime_get_ns), \ 415 + FN(trace_printk), \ 416 + FN(get_prandom_u32), \ 417 + FN(get_smp_processor_id), \ 418 + FN(skb_store_bytes), \ 419 + FN(l3_csum_replace), \ 420 + FN(l4_csum_replace), \ 421 + FN(tail_call), \ 422 + FN(clone_redirect), \ 423 + FN(get_current_pid_tgid), \ 424 + FN(get_current_uid_gid), \ 425 + FN(get_current_comm), \ 426 + FN(get_cgroup_classid), \ 427 + FN(skb_vlan_push), \ 428 + FN(skb_vlan_pop), \ 429 + FN(skb_get_tunnel_key), \ 430 + FN(skb_set_tunnel_key), \ 431 + FN(perf_event_read), \ 432 + FN(redirect), \ 433 + FN(get_route_realm), \ 434 + FN(perf_event_output), \ 435 + FN(skb_load_bytes), \ 436 + FN(get_stackid), \ 437 + FN(csum_diff), \ 438 + FN(skb_get_tunnel_opt), \ 439 + FN(skb_set_tunnel_opt), \ 440 + FN(skb_change_proto), \ 441 + FN(skb_change_type), \ 442 + FN(skb_under_cgroup), \ 443 + FN(get_hash_recalc), \ 444 + FN(get_current_task), \ 445 + FN(probe_write_user), \ 446 + FN(current_task_under_cgroup), \ 447 + FN(skb_change_tail), \ 448 + FN(skb_pull_data), \ 449 + FN(csum_update), \ 450 + FN(set_hash_invalid), \ 451 + FN(get_numa_node_id), \ 452 + FN(skb_change_head), \ 453 + FN(xdp_adjust_head), 170 454 171 455 /* integer value in 'imm' field of BPF_CALL instruction selects which helper 172 456 * function eBPF program intends to call 173 457 */ 458 + #define __BPF_ENUM_FN(x) BPF_FUNC_ ## x 174 459 enum bpf_func_id { 175 - BPF_FUNC_unspec, 176 - BPF_FUNC_map_lookup_elem, /* void *map_lookup_elem(&map, &key) */ 177 - BPF_FUNC_map_update_elem, /* int map_update_elem(&map, &key, &value, flags) */ 178 - BPF_FUNC_map_delete_elem, /* int map_delete_elem(&map, &key) */ 179 - BPF_FUNC_probe_read, /* int bpf_probe_read(void *dst, int size, void *src) */ 180 - BPF_FUNC_ktime_get_ns, /* u64 bpf_ktime_get_ns(void) */ 181 - BPF_FUNC_trace_printk, /* int bpf_trace_printk(const char *fmt, int fmt_size, ...) */ 182 - BPF_FUNC_get_prandom_u32, /* u32 prandom_u32(void) */ 183 - BPF_FUNC_get_smp_processor_id, /* u32 raw_smp_processor_id(void) */ 184 - 185 - /** 186 - * skb_store_bytes(skb, offset, from, len, flags) - store bytes into packet 187 - * @skb: pointer to skb 188 - * @offset: offset within packet from skb->mac_header 189 - * @from: pointer where to copy bytes from 190 - * @len: number of bytes to store into packet 191 - * @flags: bit 0 - if true, recompute skb->csum 192 - * other bits - reserved 193 - * Return: 0 on success 194 - */ 195 - BPF_FUNC_skb_store_bytes, 196 - 197 - /** 198 - * l3_csum_replace(skb, offset, from, to, flags) - recompute IP checksum 199 - * @skb: pointer to skb 200 - * @offset: offset within packet where IP checksum is located 201 - * @from: old value of header field 202 - * @to: new value of header field 203 - * @flags: bits 0-3 - size of header field 204 - * other bits - reserved 205 - * Return: 0 on success 206 - */ 207 - BPF_FUNC_l3_csum_replace, 208 - 209 - /** 210 - * l4_csum_replace(skb, offset, from, to, flags) - recompute TCP/UDP checksum 211 - * @skb: pointer to skb 212 - * @offset: offset within packet where TCP/UDP checksum is located 213 - * @from: old value of header field 214 - * @to: new value of header field 215 - * @flags: bits 0-3 - size of header field 216 - * bit 4 - is pseudo header 217 - * other bits - reserved 218 - * Return: 0 on success 219 - */ 220 - BPF_FUNC_l4_csum_replace, 221 - 222 - /** 223 - * bpf_tail_call(ctx, prog_array_map, index) - jump into another BPF program 224 - * @ctx: context pointer passed to next program 225 - * @prog_array_map: pointer to map which type is BPF_MAP_TYPE_PROG_ARRAY 226 - * @index: index inside array that selects specific program to run 227 - * Return: 0 on success 228 - */ 229 - BPF_FUNC_tail_call, 230 - 231 - /** 232 - * bpf_clone_redirect(skb, ifindex, flags) - redirect to another netdev 233 - * @skb: pointer to skb 234 - * @ifindex: ifindex of the net device 235 - * @flags: bit 0 - if set, redirect to ingress instead of egress 236 - * other bits - reserved 237 - * Return: 0 on success 238 - */ 239 - BPF_FUNC_clone_redirect, 240 - 241 - /** 242 - * u64 bpf_get_current_pid_tgid(void) 243 - * Return: current->tgid << 32 | current->pid 244 - */ 245 - BPF_FUNC_get_current_pid_tgid, 246 - 247 - /** 248 - * u64 bpf_get_current_uid_gid(void) 249 - * Return: current_gid << 32 | current_uid 250 - */ 251 - BPF_FUNC_get_current_uid_gid, 252 - 253 - /** 254 - * bpf_get_current_comm(char *buf, int size_of_buf) 255 - * stores current->comm into buf 256 - * Return: 0 on success 257 - */ 258 - BPF_FUNC_get_current_comm, 259 - 260 - /** 261 - * bpf_get_cgroup_classid(skb) - retrieve a proc's classid 262 - * @skb: pointer to skb 263 - * Return: classid if != 0 264 - */ 265 - BPF_FUNC_get_cgroup_classid, 266 - BPF_FUNC_skb_vlan_push, /* bpf_skb_vlan_push(skb, vlan_proto, vlan_tci) */ 267 - BPF_FUNC_skb_vlan_pop, /* bpf_skb_vlan_pop(skb) */ 268 - 269 - /** 270 - * bpf_skb_[gs]et_tunnel_key(skb, key, size, flags) 271 - * retrieve or populate tunnel metadata 272 - * @skb: pointer to skb 273 - * @key: pointer to 'struct bpf_tunnel_key' 274 - * @size: size of 'struct bpf_tunnel_key' 275 - * @flags: room for future extensions 276 - * Retrun: 0 on success 277 - */ 278 - BPF_FUNC_skb_get_tunnel_key, 279 - BPF_FUNC_skb_set_tunnel_key, 280 - BPF_FUNC_perf_event_read, /* u64 bpf_perf_event_read(&map, index) */ 281 - /** 282 - * bpf_redirect(ifindex, flags) - redirect to another netdev 283 - * @ifindex: ifindex of the net device 284 - * @flags: bit 0 - if set, redirect to ingress instead of egress 285 - * other bits - reserved 286 - * Return: TC_ACT_REDIRECT 287 - */ 288 - BPF_FUNC_redirect, 289 - 290 - /** 291 - * bpf_get_route_realm(skb) - retrieve a dst's tclassid 292 - * @skb: pointer to skb 293 - * Return: realm if != 0 294 - */ 295 - BPF_FUNC_get_route_realm, 296 - 297 - /** 298 - * bpf_perf_event_output(ctx, map, index, data, size) - output perf raw sample 299 - * @ctx: struct pt_regs* 300 - * @map: pointer to perf_event_array map 301 - * @index: index of event in the map 302 - * @data: data on stack to be output as raw data 303 - * @size: size of data 304 - * Return: 0 on success 305 - */ 306 - BPF_FUNC_perf_event_output, 307 - BPF_FUNC_skb_load_bytes, 308 - 309 - /** 310 - * bpf_get_stackid(ctx, map, flags) - walk user or kernel stack and return id 311 - * @ctx: struct pt_regs* 312 - * @map: pointer to stack_trace map 313 - * @flags: bits 0-7 - numer of stack frames to skip 314 - * bit 8 - collect user stack instead of kernel 315 - * bit 9 - compare stacks by hash only 316 - * bit 10 - if two different stacks hash into the same stackid 317 - * discard old 318 - * other bits - reserved 319 - * Return: >= 0 stackid on success or negative error 320 - */ 321 - BPF_FUNC_get_stackid, 322 - 323 - /** 324 - * bpf_csum_diff(from, from_size, to, to_size, seed) - calculate csum diff 325 - * @from: raw from buffer 326 - * @from_size: length of from buffer 327 - * @to: raw to buffer 328 - * @to_size: length of to buffer 329 - * @seed: optional seed 330 - * Return: csum result 331 - */ 332 - BPF_FUNC_csum_diff, 333 - 334 - /** 335 - * bpf_skb_[gs]et_tunnel_opt(skb, opt, size) 336 - * retrieve or populate tunnel options metadata 337 - * @skb: pointer to skb 338 - * @opt: pointer to raw tunnel option data 339 - * @size: size of @opt 340 - * Return: 0 on success for set, option size for get 341 - */ 342 - BPF_FUNC_skb_get_tunnel_opt, 343 - BPF_FUNC_skb_set_tunnel_opt, 344 - 345 - /** 346 - * bpf_skb_change_proto(skb, proto, flags) 347 - * Change protocol of the skb. Currently supported is 348 - * v4 -> v6, v6 -> v4 transitions. The helper will also 349 - * resize the skb. eBPF program is expected to fill the 350 - * new headers via skb_store_bytes and lX_csum_replace. 351 - * @skb: pointer to skb 352 - * @proto: new skb->protocol type 353 - * @flags: reserved 354 - * Return: 0 on success or negative error 355 - */ 356 - BPF_FUNC_skb_change_proto, 357 - 358 - /** 359 - * bpf_skb_change_type(skb, type) 360 - * Change packet type of skb. 361 - * @skb: pointer to skb 362 - * @type: new skb->pkt_type type 363 - * Return: 0 on success or negative error 364 - */ 365 - BPF_FUNC_skb_change_type, 366 - 367 - /** 368 - * bpf_skb_under_cgroup(skb, map, index) - Check cgroup2 membership of skb 369 - * @skb: pointer to skb 370 - * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type 371 - * @index: index of the cgroup in the bpf_map 372 - * Return: 373 - * == 0 skb failed the cgroup2 descendant test 374 - * == 1 skb succeeded the cgroup2 descendant test 375 - * < 0 error 376 - */ 377 - BPF_FUNC_skb_under_cgroup, 378 - 379 - /** 380 - * bpf_get_hash_recalc(skb) 381 - * Retrieve and possibly recalculate skb->hash. 382 - * @skb: pointer to skb 383 - * Return: hash 384 - */ 385 - BPF_FUNC_get_hash_recalc, 386 - 387 - /** 388 - * u64 bpf_get_current_task(void) 389 - * Returns current task_struct 390 - * Return: current 391 - */ 392 - BPF_FUNC_get_current_task, 393 - 394 - /** 395 - * bpf_probe_write_user(void *dst, void *src, int len) 396 - * safely attempt to write to a location 397 - * @dst: destination address in userspace 398 - * @src: source address on stack 399 - * @len: number of bytes to copy 400 - * Return: 0 on success or negative error 401 - */ 402 - BPF_FUNC_probe_write_user, 403 - 460 + __BPF_FUNC_MAPPER(__BPF_ENUM_FN) 404 461 __BPF_FUNC_MAX_ID, 405 462 }; 463 + #undef __BPF_ENUM_FN 406 464 407 465 /* All flags used by eBPF helper functions, placed here. */ 408 466 ··· 559 449 __u16 tunnel_ext; 560 450 __u32 tunnel_label; 561 451 }; 452 + 453 + /* Generic BPF return codes which all BPF program types may support. 454 + * The values are binary compatible with their TC_ACT_* counter-part to 455 + * provide backwards compatibility with existing SCHED_CLS and SCHED_ACT 456 + * programs. 457 + * 458 + * XDP is handled seprately, see XDP_*. 459 + */ 460 + enum bpf_ret_code { 461 + BPF_OK = 0, 462 + /* 1 reserved */ 463 + BPF_DROP = 2, 464 + /* 3-6 reserved */ 465 + BPF_REDIRECT = 7, 466 + /* >127 are reserved for prog type specific return codes */ 467 + }; 468 + 469 + struct bpf_sock { 470 + __u32 bound_dev_if; 471 + __u32 family; 472 + __u32 type; 473 + __u32 protocol; 474 + }; 475 + 476 + #define XDP_PACKET_HEADROOM 256 562 477 563 478 /* User return codes for XDP prog type. 564 479 * A valid XDP program must return one of these defined values. All other
+27 -3
tools/lib/bpf/bpf.c
··· 54 54 } 55 55 56 56 int bpf_create_map(enum bpf_map_type map_type, int key_size, 57 - int value_size, int max_entries) 57 + int value_size, int max_entries, __u32 map_flags) 58 58 { 59 59 union bpf_attr attr; 60 60 ··· 64 64 attr.key_size = key_size; 65 65 attr.value_size = value_size; 66 66 attr.max_entries = max_entries; 67 + attr.map_flags = map_flags; 67 68 68 69 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); 69 70 } 70 71 71 72 int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns, 72 73 size_t insns_cnt, char *license, 73 - u32 kern_version, char *log_buf, size_t log_buf_sz) 74 + __u32 kern_version, char *log_buf, size_t log_buf_sz) 74 75 { 75 76 int fd; 76 77 union bpf_attr attr; ··· 99 98 } 100 99 101 100 int bpf_map_update_elem(int fd, void *key, void *value, 102 - u64 flags) 101 + __u64 flags) 103 102 { 104 103 union bpf_attr attr; 105 104 ··· 166 165 attr.pathname = ptr_to_u64((void *)pathname); 167 166 168 167 return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr)); 168 + } 169 + 170 + int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type) 171 + { 172 + union bpf_attr attr; 173 + 174 + bzero(&attr, sizeof(attr)); 175 + attr.target_fd = target_fd; 176 + attr.attach_bpf_fd = prog_fd; 177 + attr.attach_type = type; 178 + 179 + return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)); 180 + } 181 + 182 + int bpf_prog_detach(int target_fd, enum bpf_attach_type type) 183 + { 184 + union bpf_attr attr; 185 + 186 + bzero(&attr, sizeof(attr)); 187 + attr.target_fd = target_fd; 188 + attr.attach_type = type; 189 + 190 + return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr)); 169 191 }
+6 -3
tools/lib/bpf/bpf.h
··· 24 24 #include <linux/bpf.h> 25 25 26 26 int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, 27 - int max_entries); 27 + int max_entries, __u32 map_flags); 28 28 29 29 /* Recommend log buffer size */ 30 30 #define BPF_LOG_BUF_SIZE 65536 31 31 int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns, 32 32 size_t insns_cnt, char *license, 33 - u32 kern_version, char *log_buf, 33 + __u32 kern_version, char *log_buf, 34 34 size_t log_buf_sz); 35 35 36 36 int bpf_map_update_elem(int fd, void *key, void *value, 37 - u64 flags); 37 + __u64 flags); 38 38 39 39 int bpf_map_lookup_elem(int fd, void *key, void *value); 40 40 int bpf_map_delete_elem(int fd, void *key); 41 41 int bpf_map_get_next_key(int fd, void *key, void *next_key); 42 42 int bpf_obj_pin(int fd, const char *pathname); 43 43 int bpf_obj_get(const char *pathname); 44 + int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type); 45 + int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type); 46 + 44 47 45 48 #endif
+2 -1
tools/lib/bpf/libbpf.c
··· 854 854 *pfd = bpf_create_map(def->type, 855 855 def->key_size, 856 856 def->value_size, 857 - def->max_entries); 857 + def->max_entries, 858 + 0); 858 859 if (*pfd < 0) { 859 860 size_t j; 860 861 int err = *pfd;
+4
tools/perf/Documentation/perf-sched.txt
··· 132 132 --migrations:: 133 133 Show migration events. 134 134 135 + -I:: 136 + --idle-hist:: 137 + Show idle-related events only. 138 + 135 139 --time:: 136 140 Only analyze samples within given time window: <start>,<stop>. Times 137 141 have the format seconds.microseconds. If start is not given (i.e., time
+1 -93
tools/perf/Makefile.perf
··· 201 201 $(goals) all: sub-make 202 202 203 203 sub-make: fixdep 204 + @./check-headers.sh 204 205 $(Q)$(MAKE) FIXDEP=1 -f Makefile.perf $(goals) 205 206 206 207 else # force_fixdep ··· 405 404 build := -f $(srctree)/tools/build/Makefile.build dir=. obj 406 405 407 406 $(PERF_IN): prepare FORCE 408 - @(test -f ../../include/uapi/linux/perf_event.h && ( \ 409 - (diff -B ../include/uapi/linux/perf_event.h ../../include/uapi/linux/perf_event.h >/dev/null) \ 410 - || echo "Warning: tools/include/uapi/linux/perf_event.h differs from kernel" >&2 )) || true 411 - @(test -f ../../include/linux/hash.h && ( \ 412 - (diff -B ../include/linux/hash.h ../../include/linux/hash.h >/dev/null) \ 413 - || echo "Warning: tools/include/linux/hash.h differs from kernel" >&2 )) || true 414 - @(test -f ../../include/uapi/linux/hw_breakpoint.h && ( \ 415 - (diff -B ../include/uapi/linux/hw_breakpoint.h ../../include/uapi/linux/hw_breakpoint.h >/dev/null) \ 416 - || echo "Warning: tools/include/uapi/linux/hw_breakpoint.h differs from kernel" >&2 )) || true 417 - @(test -f ../../arch/x86/include/asm/disabled-features.h && ( \ 418 - (diff -B ../arch/x86/include/asm/disabled-features.h ../../arch/x86/include/asm/disabled-features.h >/dev/null) \ 419 - || echo "Warning: tools/arch/x86/include/asm/disabled-features.h differs from kernel" >&2 )) || true 420 - @(test -f ../../arch/x86/include/asm/required-features.h && ( \ 421 - (diff -B ../arch/x86/include/asm/required-features.h ../../arch/x86/include/asm/required-features.h >/dev/null) \ 422 - || echo "Warning: tools/arch/x86/include/asm/required-features.h differs from kernel" >&2 )) || true 423 - @(test -f ../../arch/x86/include/asm/cpufeatures.h && ( \ 424 - (diff -B ../arch/x86/include/asm/cpufeatures.h ../../arch/x86/include/asm/cpufeatures.h >/dev/null) \ 425 - || echo "Warning: tools/arch/x86/include/asm/cpufeatures.h differs from kernel" >&2 )) || true 426 - @(test -f ../../arch/x86/lib/memcpy_64.S && ( \ 427 - (diff -B -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" ../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memcpy_64.S >/dev/null) \ 428 - || echo "Warning: tools/arch/x86/lib/memcpy_64.S differs from kernel" >&2 )) || true 429 - @(test -f ../../arch/x86/lib/memset_64.S && ( \ 430 - (diff -B -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" ../arch/x86/lib/memset_64.S ../../arch/x86/lib/memset_64.S >/dev/null) \ 431 - || echo "Warning: tools/arch/x86/lib/memset_64.S differs from kernel" >&2 )) || true 432 - @(test -f ../../arch/arm/include/uapi/asm/perf_regs.h && ( \ 433 - (diff -B ../arch/arm/include/uapi/asm/perf_regs.h ../../arch/arm/include/uapi/asm/perf_regs.h >/dev/null) \ 434 - || echo "Warning: tools/arch/arm/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true 435 - @(test -f ../../arch/arm64/include/uapi/asm/perf_regs.h && ( \ 436 - (diff -B ../arch/arm64/include/uapi/asm/perf_regs.h ../../arch/arm64/include/uapi/asm/perf_regs.h >/dev/null) \ 437 - || echo "Warning: tools/arch/arm64/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true 438 - @(test -f ../../arch/powerpc/include/uapi/asm/perf_regs.h && ( \ 439 - (diff -B ../arch/powerpc/include/uapi/asm/perf_regs.h ../../arch/powerpc/include/uapi/asm/perf_regs.h >/dev/null) \ 440 - || echo "Warning: tools/arch/powerpc/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true 441 - @(test -f ../../arch/x86/include/uapi/asm/perf_regs.h && ( \ 442 - (diff -B ../arch/x86/include/uapi/asm/perf_regs.h ../../arch/x86/include/uapi/asm/perf_regs.h >/dev/null) \ 443 - || echo "Warning: tools/arch/x86/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true 444 - @(test -f ../../arch/x86/include/uapi/asm/kvm.h && ( \ 445 - (diff -B ../arch/x86/include/uapi/asm/kvm.h ../../arch/x86/include/uapi/asm/kvm.h >/dev/null) \ 446 - || echo "Warning: tools/arch/x86/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true 447 - @(test -f ../../arch/x86/include/uapi/asm/kvm_perf.h && ( \ 448 - (diff -B ../arch/x86/include/uapi/asm/kvm_perf.h ../../arch/x86/include/uapi/asm/kvm_perf.h >/dev/null) \ 449 - || echo "Warning: tools/arch/x86/include/uapi/asm/kvm_perf.h differs from kernel" >&2 )) || true 450 - @(test -f ../../arch/x86/include/uapi/asm/svm.h && ( \ 451 - (diff -B ../arch/x86/include/uapi/asm/svm.h ../../arch/x86/include/uapi/asm/svm.h >/dev/null) \ 452 - || echo "Warning: tools/arch/x86/include/uapi/asm/svm.h differs from kernel" >&2 )) || true 453 - @(test -f ../../arch/x86/include/uapi/asm/vmx.h && ( \ 454 - (diff -B ../arch/x86/include/uapi/asm/vmx.h ../../arch/x86/include/uapi/asm/vmx.h >/dev/null) \ 455 - || echo "Warning: tools/arch/x86/include/uapi/asm/vmx.h differs from kernel" >&2 )) || true 456 - @(test -f ../../arch/powerpc/include/uapi/asm/kvm.h && ( \ 457 - (diff -B ../arch/powerpc/include/uapi/asm/kvm.h ../../arch/powerpc/include/uapi/asm/kvm.h >/dev/null) \ 458 - || echo "Warning: tools/arch/powerpc/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true 459 - @(test -f ../../arch/s390/include/uapi/asm/kvm.h && ( \ 460 - (diff -B ../arch/s390/include/uapi/asm/kvm.h ../../arch/s390/include/uapi/asm/kvm.h >/dev/null) \ 461 - || echo "Warning: tools/arch/s390/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true 462 - @(test -f ../../arch/s390/include/uapi/asm/kvm_perf.h && ( \ 463 - (diff -B ../arch/s390/include/uapi/asm/kvm_perf.h ../../arch/s390/include/uapi/asm/kvm_perf.h >/dev/null) \ 464 - || echo "Warning: tools/arch/s390/include/uapi/asm/kvm_perf.h differs from kernel" >&2 )) || true 465 - @(test -f ../../arch/s390/include/uapi/asm/sie.h && ( \ 466 - (diff -B ../arch/s390/include/uapi/asm/sie.h ../../arch/s390/include/uapi/asm/sie.h >/dev/null) \ 467 - || echo "Warning: tools/arch/s390/include/uapi/asm/sie.h differs from kernel" >&2 )) || true 468 - @(test -f ../../arch/arm/include/uapi/asm/kvm.h && ( \ 469 - (diff -B ../arch/arm/include/uapi/asm/kvm.h ../../arch/arm/include/uapi/asm/kvm.h >/dev/null) \ 470 - || echo "Warning: tools/arch/arm/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true 471 - @(test -f ../../arch/arm64/include/uapi/asm/kvm.h && ( \ 472 - (diff -B ../arch/arm64/include/uapi/asm/kvm.h ../../arch/arm64/include/uapi/asm/kvm.h >/dev/null) \ 473 - || echo "Warning: tools/arch/arm64/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true 474 - @(test -f ../../include/asm-generic/bitops/arch_hweight.h && ( \ 475 - (diff -B ../include/asm-generic/bitops/arch_hweight.h ../../include/asm-generic/bitops/arch_hweight.h >/dev/null) \ 476 - || echo "Warning: tools/include/asm-generic/bitops/arch_hweight.h differs from kernel" >&2 )) || true 477 - @(test -f ../../include/asm-generic/bitops/const_hweight.h && ( \ 478 - (diff -B ../include/asm-generic/bitops/const_hweight.h ../../include/asm-generic/bitops/const_hweight.h >/dev/null) \ 479 - || echo "Warning: tools/include/asm-generic/bitops/const_hweight.h differs from kernel" >&2 )) || true 480 - @(test -f ../../include/asm-generic/bitops/__fls.h && ( \ 481 - (diff -B ../include/asm-generic/bitops/__fls.h ../../include/asm-generic/bitops/__fls.h >/dev/null) \ 482 - || echo "Warning: tools/include/asm-generic/bitops/__fls.h differs from kernel" >&2 )) || true 483 - @(test -f ../../include/asm-generic/bitops/fls.h && ( \ 484 - (diff -B ../include/asm-generic/bitops/fls.h ../../include/asm-generic/bitops/fls.h >/dev/null) \ 485 - || echo "Warning: tools/include/asm-generic/bitops/fls.h differs from kernel" >&2 )) || true 486 - @(test -f ../../include/asm-generic/bitops/fls64.h && ( \ 487 - (diff -B ../include/asm-generic/bitops/fls64.h ../../include/asm-generic/bitops/fls64.h >/dev/null) \ 488 - || echo "Warning: tools/include/asm-generic/bitops/fls64.h differs from kernel" >&2 )) || true 489 - @(test -f ../../include/linux/coresight-pmu.h && ( \ 490 - (diff -B ../include/linux/coresight-pmu.h ../../include/linux/coresight-pmu.h >/dev/null) \ 491 - || echo "Warning: tools/include/linux/coresight-pmu.h differs from kernel" >&2 )) || true 492 - @(test -f ../../include/uapi/asm-generic/mman-common.h && ( \ 493 - (diff -B ../include/uapi/asm-generic/mman-common.h ../../include/uapi/asm-generic/mman-common.h >/dev/null) \ 494 - || echo "Warning: tools/include/uapi/asm-generic/mman-common.h differs from kernel" >&2 )) || true 495 - @(test -f ../../include/uapi/asm-generic/mman.h && ( \ 496 - (diff -B -I "^#include <\(uapi/\)*asm-generic/mman-common.h>$$" ../include/uapi/asm-generic/mman.h ../../include/uapi/asm-generic/mman.h >/dev/null) \ 497 - || echo "Warning: tools/include/uapi/asm-generic/mman.h differs from kernel" >&2 )) || true 498 - @(test -f ../../include/uapi/linux/mman.h && ( \ 499 - (diff -B -I "^#include <\(uapi/\)*asm/mman.h>$$" ../include/uapi/linux/mman.h ../../include/uapi/linux/mman.h >/dev/null) \ 500 - || echo "Warning: tools/include/uapi/linux/mman.h differs from kernel" >&2 )) || true 501 407 $(Q)$(MAKE) $(build)=perf 502 408 503 409 $(JEVENTS_IN): FORCE
+1 -1
tools/perf/bench/futex-lock-pi.c
··· 48 48 }; 49 49 50 50 static const char * const bench_futex_lock_pi_usage[] = { 51 - "perf bench futex requeue <options>", 51 + "perf bench futex lock-pi <options>", 52 52 NULL 53 53 }; 54 54
+6 -7
tools/perf/builtin-c2c.c
··· 208 208 static int process_sample_event(struct perf_tool *tool __maybe_unused, 209 209 union perf_event *event, 210 210 struct perf_sample *sample, 211 - struct perf_evsel *evsel __maybe_unused, 211 + struct perf_evsel *evsel, 212 212 struct machine *machine) 213 213 { 214 214 struct c2c_hists *c2c_hists = &c2c.hists; ··· 379 379 380 380 static int c2c_width(struct perf_hpp_fmt *fmt, 381 381 struct perf_hpp *hpp __maybe_unused, 382 - struct hists *hists __maybe_unused) 382 + struct hists *hists) 383 383 { 384 384 struct c2c_fmt *c2c_fmt; 385 385 struct c2c_dimension *dim; ··· 1127 1127 MEAN_ENTRY(mean_load_entry, load); 1128 1128 1129 1129 static int 1130 - cpucnt_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp, 1130 + cpucnt_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1131 1131 struct hist_entry *he) 1132 1132 { 1133 1133 struct c2c_hist_entry *c2c_he; ··· 1141 1141 } 1142 1142 1143 1143 static int 1144 - cl_idx_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp, 1144 + cl_idx_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1145 1145 struct hist_entry *he) 1146 1146 { 1147 1147 struct c2c_hist_entry *c2c_he; ··· 1155 1155 } 1156 1156 1157 1157 static int 1158 - cl_idx_empty_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp, 1158 + cl_idx_empty_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1159 1159 struct hist_entry *he) 1160 1160 { 1161 1161 int width = c2c_width(fmt, hpp, he->hists); ··· 1779 1779 return hpp_list__parse(&hists->list, NULL, sort); 1780 1780 } 1781 1781 1782 - __maybe_unused 1783 1782 static int c2c_hists__reinit(struct c2c_hists *c2c_hists, 1784 1783 const char *output, 1785 1784 const char *sort) ··· 2657 2658 return err; 2658 2659 } 2659 2660 2660 - static int parse_record_events(const struct option *opt __maybe_unused, 2661 + static int parse_record_events(const struct option *opt, 2661 2662 const char *str, int unset __maybe_unused) 2662 2663 { 2663 2664 bool *event_set = (bool *) opt->value;
+2 -2
tools/perf/builtin-mem.c
··· 70 70 OPT_UINTEGER(0, "ldlat", &perf_mem_events__loads_ldlat, "mem-loads latency"), 71 71 OPT_INCR('v', "verbose", &verbose, 72 72 "be more verbose (show counter open errors, etc)"), 73 - OPT_BOOLEAN('U', "--all-user", &all_user, "collect only user level data"), 74 - OPT_BOOLEAN('K', "--all-kernel", &all_kernel, "collect only kernel level data"), 73 + OPT_BOOLEAN('U', "all-user", &all_user, "collect only user level data"), 74 + OPT_BOOLEAN('K', "all-kernel", &all_kernel, "collect only kernel level data"), 75 75 OPT_END() 76 76 }; 77 77
+3
tools/perf/builtin-record.c
··· 1687 1687 goto out; 1688 1688 } 1689 1689 1690 + /* Enable ignoring missing threads when -u option is defined. */ 1691 + rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX; 1692 + 1690 1693 err = -ENOMEM; 1691 1694 if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1692 1695 usage_with_options(record_usage, record_options);
+1 -1
tools/perf/builtin-report.c
··· 648 648 } 649 649 650 650 static int 651 - parse_branch_mode(const struct option *opt __maybe_unused, 651 + parse_branch_mode(const struct option *opt, 652 652 const char *str __maybe_unused, int unset) 653 653 { 654 654 int *branch_mode = opt->value;
+233 -42
tools/perf/builtin-sched.c
··· 200 200 /* options for timehist command */ 201 201 bool summary; 202 202 bool summary_only; 203 + bool idle_hist; 203 204 bool show_callchain; 204 205 unsigned int max_stack; 205 206 bool show_cpu_visual; ··· 229 228 struct evsel_runtime { 230 229 u64 *last_time; /* time this event was last seen per cpu */ 231 230 u32 ncpu; /* highest cpu slot allocated */ 231 + }; 232 + 233 + /* per cpu idle time data */ 234 + struct idle_thread_runtime { 235 + struct thread_runtime tr; 236 + struct thread *last_thread; 237 + struct rb_root sorted_root; 238 + struct callchain_root callchain; 239 + struct callchain_cursor cursor; 232 240 }; 233 241 234 242 /* track idle times per cpu */ ··· 1775 1765 return r->last_time[cpu]; 1776 1766 } 1777 1767 1778 - static int comm_width = 20; 1768 + static int comm_width = 30; 1779 1769 1780 1770 static char *timehist_get_commstr(struct thread *thread) 1781 1771 { ··· 1817 1807 printf(" "); 1818 1808 } 1819 1809 1820 - printf(" %-20s %9s %9s %9s", 1810 + printf(" %-*s %9s %9s %9s", comm_width, 1821 1811 "task name", "wait time", "sch delay", "run time"); 1822 1812 1823 1813 printf("\n"); ··· 1830 1820 if (sched->show_cpu_visual) 1831 1821 printf(" %*s ", ncpus, ""); 1832 1822 1833 - printf(" %-20s %9s %9s %9s\n", "[tid/pid]", "(msec)", "(msec)", "(msec)"); 1823 + printf(" %-*s %9s %9s %9s\n", comm_width, 1824 + "[tid/pid]", "(msec)", "(msec)", "(msec)"); 1834 1825 1835 1826 /* 1836 1827 * separator ··· 1841 1830 if (sched->show_cpu_visual) 1842 1831 printf(" %.*s ", ncpus, graph_dotted_line); 1843 1832 1844 - printf(" %.20s %.9s %.9s %.9s", 1833 + printf(" %.*s %.9s %.9s %.9s", comm_width, 1845 1834 graph_dotted_line, graph_dotted_line, graph_dotted_line, 1846 1835 graph_dotted_line); 1847 1836 ··· 1950 1939 r->total_run_time += r->dt_run; 1951 1940 } 1952 1941 1953 - static bool is_idle_sample(struct perf_sched *sched, 1954 - struct perf_sample *sample, 1955 - struct perf_evsel *evsel, 1956 - struct machine *machine) 1942 + static bool is_idle_sample(struct perf_sample *sample, 1943 + struct perf_evsel *evsel) 1957 1944 { 1958 - struct thread *thread; 1959 - struct callchain_cursor *cursor = &callchain_cursor; 1960 - 1961 1945 /* pid 0 == swapper == idle task */ 1962 - if (sample->pid == 0) 1963 - return true; 1946 + if (strcmp(perf_evsel__name(evsel), "sched:sched_switch") == 0) 1947 + return perf_evsel__intval(evsel, sample, "prev_pid") == 0; 1964 1948 1965 - if (strcmp(perf_evsel__name(evsel), "sched:sched_switch") == 0) { 1966 - if (perf_evsel__intval(evsel, sample, "prev_pid") == 0) 1967 - return true; 1968 - } 1949 + return sample->pid == 0; 1950 + } 1951 + 1952 + static void save_task_callchain(struct perf_sched *sched, 1953 + struct perf_sample *sample, 1954 + struct perf_evsel *evsel, 1955 + struct machine *machine) 1956 + { 1957 + struct callchain_cursor *cursor = &callchain_cursor; 1958 + struct thread *thread; 1969 1959 1970 1960 /* want main thread for process - has maps */ 1971 1961 thread = machine__findnew_thread(machine, sample->pid, sample->pid); 1972 1962 if (thread == NULL) { 1973 1963 pr_debug("Failed to get thread for pid %d.\n", sample->pid); 1974 - return false; 1964 + return; 1975 1965 } 1976 1966 1977 1967 if (!symbol_conf.use_callchain || sample->callchain == NULL) 1978 - return false; 1968 + return; 1979 1969 1980 1970 if (thread__resolve_callchain(thread, cursor, evsel, sample, 1981 1971 NULL, NULL, sched->max_stack + 2) != 0) { 1982 1972 if (verbose) 1983 1973 error("Failed to resolve callchain. Skipping\n"); 1984 1974 1985 - return false; 1975 + return; 1986 1976 } 1987 1977 1988 1978 callchain_cursor_commit(cursor); ··· 2006 1994 2007 1995 callchain_cursor_advance(cursor); 2008 1996 } 1997 + } 2009 1998 2010 - return false; 1999 + static int init_idle_thread(struct thread *thread) 2000 + { 2001 + struct idle_thread_runtime *itr; 2002 + 2003 + thread__set_comm(thread, idle_comm, 0); 2004 + 2005 + itr = zalloc(sizeof(*itr)); 2006 + if (itr == NULL) 2007 + return -ENOMEM; 2008 + 2009 + init_stats(&itr->tr.run_stats); 2010 + callchain_init(&itr->callchain); 2011 + callchain_cursor_reset(&itr->cursor); 2012 + thread__set_priv(thread, itr); 2013 + 2014 + return 0; 2011 2015 } 2012 2016 2013 2017 /* ··· 2032 2004 */ 2033 2005 static int init_idle_threads(int ncpu) 2034 2006 { 2035 - int i; 2007 + int i, ret; 2036 2008 2037 2009 idle_threads = zalloc(ncpu * sizeof(struct thread *)); 2038 2010 if (!idle_threads) ··· 2046 2018 if (idle_threads[i] == NULL) 2047 2019 return -ENOMEM; 2048 2020 2049 - thread__set_comm(idle_threads[i], idle_comm, 0); 2021 + ret = init_idle_thread(idle_threads[i]); 2022 + if (ret < 0) 2023 + return ret; 2050 2024 } 2051 2025 2052 2026 return 0; ··· 2095 2065 idle_threads[cpu] = thread__new(0, 0); 2096 2066 2097 2067 if (idle_threads[cpu]) { 2098 - idle_threads[cpu]->tid = 0; 2099 - thread__set_comm(idle_threads[cpu], idle_comm, 0); 2068 + if (init_idle_thread(idle_threads[cpu]) < 0) 2069 + return NULL; 2100 2070 } 2101 2071 } 2102 2072 2103 2073 return idle_threads[cpu]; 2074 + } 2075 + 2076 + static void save_idle_callchain(struct idle_thread_runtime *itr, 2077 + struct perf_sample *sample) 2078 + { 2079 + if (!symbol_conf.use_callchain || sample->callchain == NULL) 2080 + return; 2081 + 2082 + callchain_cursor__copy(&itr->cursor, &callchain_cursor); 2104 2083 } 2105 2084 2106 2085 /* ··· 2150 2111 { 2151 2112 struct thread *thread; 2152 2113 2153 - if (is_idle_sample(sched, sample, evsel, machine)) { 2114 + if (is_idle_sample(sample, evsel)) { 2154 2115 thread = get_idle_thread(sample->cpu); 2155 2116 if (thread == NULL) 2156 2117 pr_err("Failed to get idle thread for cpu %d.\n", sample->cpu); ··· 2163 2124 pr_debug("Failed to get thread for tid %d. skipping sample.\n", 2164 2125 sample->tid); 2165 2126 } 2127 + 2128 + save_task_callchain(sched, sample, evsel, machine); 2129 + if (sched->idle_hist) { 2130 + struct thread *idle; 2131 + struct idle_thread_runtime *itr; 2132 + 2133 + idle = get_idle_thread(sample->cpu); 2134 + if (idle == NULL) { 2135 + pr_err("Failed to get idle thread for cpu %d.\n", sample->cpu); 2136 + return NULL; 2137 + } 2138 + 2139 + itr = thread__priv(idle); 2140 + if (itr == NULL) 2141 + return NULL; 2142 + 2143 + itr->last_thread = thread; 2144 + 2145 + /* copy task callchain when entering to idle */ 2146 + if (perf_evsel__intval(evsel, sample, "next_pid") == 0) 2147 + save_idle_callchain(itr, sample); 2148 + } 2166 2149 } 2167 2150 2168 2151 return thread; 2169 2152 } 2170 2153 2171 2154 static bool timehist_skip_sample(struct perf_sched *sched, 2172 - struct thread *thread) 2155 + struct thread *thread, 2156 + struct perf_evsel *evsel, 2157 + struct perf_sample *sample) 2173 2158 { 2174 2159 bool rc = false; 2175 2160 ··· 2202 2139 sched->skipped_samples++; 2203 2140 } 2204 2141 2142 + if (sched->idle_hist) { 2143 + if (strcmp(perf_evsel__name(evsel), "sched:sched_switch")) 2144 + rc = true; 2145 + else if (perf_evsel__intval(evsel, sample, "prev_pid") != 0 && 2146 + perf_evsel__intval(evsel, sample, "next_pid") != 0) 2147 + rc = true; 2148 + } 2149 + 2205 2150 return rc; 2206 2151 } 2207 2152 2208 2153 static void timehist_print_wakeup_event(struct perf_sched *sched, 2154 + struct perf_evsel *evsel, 2209 2155 struct perf_sample *sample, 2210 2156 struct machine *machine, 2211 2157 struct thread *awakened) ··· 2227 2155 return; 2228 2156 2229 2157 /* show wakeup unless both awakee and awaker are filtered */ 2230 - if (timehist_skip_sample(sched, thread) && 2231 - timehist_skip_sample(sched, awakened)) { 2158 + if (timehist_skip_sample(sched, thread, evsel, sample) && 2159 + timehist_skip_sample(sched, awakened, evsel, sample)) { 2232 2160 return; 2233 2161 } 2234 2162 ··· 2273 2201 /* show wakeups if requested */ 2274 2202 if (sched->show_wakeups && 2275 2203 !perf_time__skip_sample(&sched->ptime, sample->time)) 2276 - timehist_print_wakeup_event(sched, sample, machine, thread); 2204 + timehist_print_wakeup_event(sched, evsel, sample, machine, thread); 2277 2205 2278 2206 return 0; 2279 2207 } ··· 2300 2228 if (thread == NULL) 2301 2229 return; 2302 2230 2303 - if (timehist_skip_sample(sched, thread) && 2304 - timehist_skip_sample(sched, migrated)) { 2231 + if (timehist_skip_sample(sched, thread, evsel, sample) && 2232 + timehist_skip_sample(sched, migrated, evsel, sample)) { 2305 2233 return; 2306 2234 } 2307 2235 ··· 2386 2314 goto out; 2387 2315 } 2388 2316 2389 - if (timehist_skip_sample(sched, thread)) 2317 + if (timehist_skip_sample(sched, thread, evsel, sample)) 2390 2318 goto out; 2391 2319 2392 2320 tr = thread__get_runtime(thread); ··· 2405 2333 if (ptime->start && ptime->start > t) 2406 2334 goto out; 2407 2335 2408 - if (ptime->start > tprev) 2336 + if (tprev && ptime->start > tprev) 2409 2337 tprev = ptime->start; 2410 2338 2411 2339 /* ··· 2422 2350 t = ptime->end; 2423 2351 } 2424 2352 2425 - timehist_update_runtime_stats(tr, t, tprev); 2353 + if (!sched->idle_hist || thread->tid == 0) { 2354 + timehist_update_runtime_stats(tr, t, tprev); 2355 + 2356 + if (sched->idle_hist) { 2357 + struct idle_thread_runtime *itr = (void *)tr; 2358 + struct thread_runtime *last_tr; 2359 + 2360 + BUG_ON(thread->tid != 0); 2361 + 2362 + if (itr->last_thread == NULL) 2363 + goto out; 2364 + 2365 + /* add current idle time as last thread's runtime */ 2366 + last_tr = thread__get_runtime(itr->last_thread); 2367 + if (last_tr == NULL) 2368 + goto out; 2369 + 2370 + timehist_update_runtime_stats(last_tr, t, tprev); 2371 + /* 2372 + * remove delta time of last thread as it's not updated 2373 + * and otherwise it will show an invalid value next 2374 + * time. we only care total run time and run stat. 2375 + */ 2376 + last_tr->dt_run = 0; 2377 + last_tr->dt_wait = 0; 2378 + last_tr->dt_delay = 0; 2379 + 2380 + if (itr->cursor.nr) 2381 + callchain_append(&itr->callchain, &itr->cursor, t - tprev); 2382 + 2383 + itr->last_thread = NULL; 2384 + } 2385 + } 2426 2386 2427 2387 if (!sched->summary_only) 2428 2388 timehist_print_sample(sched, sample, &al, thread, t); ··· 2561 2457 return __show_thread_runtime(t, priv); 2562 2458 } 2563 2459 2460 + static size_t callchain__fprintf_folded(FILE *fp, struct callchain_node *node) 2461 + { 2462 + const char *sep = " <- "; 2463 + struct callchain_list *chain; 2464 + size_t ret = 0; 2465 + char bf[1024]; 2466 + bool first; 2467 + 2468 + if (node == NULL) 2469 + return 0; 2470 + 2471 + ret = callchain__fprintf_folded(fp, node->parent); 2472 + first = (ret == 0); 2473 + 2474 + list_for_each_entry(chain, &node->val, list) { 2475 + if (chain->ip >= PERF_CONTEXT_MAX) 2476 + continue; 2477 + if (chain->ms.sym && chain->ms.sym->ignore) 2478 + continue; 2479 + ret += fprintf(fp, "%s%s", first ? "" : sep, 2480 + callchain_list__sym_name(chain, bf, sizeof(bf), 2481 + false)); 2482 + first = false; 2483 + } 2484 + 2485 + return ret; 2486 + } 2487 + 2488 + static size_t timehist_print_idlehist_callchain(struct rb_root *root) 2489 + { 2490 + size_t ret = 0; 2491 + FILE *fp = stdout; 2492 + struct callchain_node *chain; 2493 + struct rb_node *rb_node = rb_first(root); 2494 + 2495 + printf(" %16s %8s %s\n", "Idle time (msec)", "Count", "Callchains"); 2496 + printf(" %.16s %.8s %.50s\n", graph_dotted_line, graph_dotted_line, 2497 + graph_dotted_line); 2498 + 2499 + while (rb_node) { 2500 + chain = rb_entry(rb_node, struct callchain_node, rb_node); 2501 + rb_node = rb_next(rb_node); 2502 + 2503 + ret += fprintf(fp, " "); 2504 + print_sched_time(chain->hit, 12); 2505 + ret += 16; /* print_sched_time returns 2nd arg + 4 */ 2506 + ret += fprintf(fp, " %8d ", chain->count); 2507 + ret += callchain__fprintf_folded(fp, chain); 2508 + ret += fprintf(fp, "\n"); 2509 + } 2510 + 2511 + return ret; 2512 + } 2513 + 2564 2514 static void timehist_print_summary(struct perf_sched *sched, 2565 2515 struct perf_session *session) 2566 2516 { ··· 2627 2469 2628 2470 memset(&totals, 0, sizeof(totals)); 2629 2471 2630 - if (comm_width < 30) 2631 - comm_width = 30; 2632 - 2633 - printf("\nRuntime summary\n"); 2634 - printf("%*s parent sched-in ", comm_width, "comm"); 2635 - printf(" run-time min-run avg-run max-run stddev migrations\n"); 2472 + if (sched->idle_hist) { 2473 + printf("\nIdle-time summary\n"); 2474 + printf("%*s parent sched-out ", comm_width, "comm"); 2475 + printf(" idle-time min-idle avg-idle max-idle stddev migrations\n"); 2476 + } else { 2477 + printf("\nRuntime summary\n"); 2478 + printf("%*s parent sched-in ", comm_width, "comm"); 2479 + printf(" run-time min-run avg-run max-run stddev migrations\n"); 2480 + } 2636 2481 printf("%*s (count) ", comm_width, ""); 2637 2482 printf(" (msec) (msec) (msec) (msec) %%\n"); 2638 2483 printf("%.117s\n", graph_dotted_line); ··· 2651 2490 printf("<no terminated tasks>\n"); 2652 2491 2653 2492 /* CPU idle stats not tracked when samples were skipped */ 2654 - if (sched->skipped_samples) 2493 + if (sched->skipped_samples && !sched->idle_hist) 2655 2494 return; 2656 2495 2657 2496 printf("\nIdle stats:\n"); ··· 2668 2507 printf(" msec\n"); 2669 2508 } else 2670 2509 printf(" CPU %2d idle entire time window\n", i); 2510 + } 2511 + 2512 + if (sched->idle_hist && symbol_conf.use_callchain) { 2513 + callchain_param.mode = CHAIN_FOLDED; 2514 + callchain_param.value = CCVAL_PERIOD; 2515 + 2516 + callchain_register_param(&callchain_param); 2517 + 2518 + printf("\nIdle stats by callchain:\n"); 2519 + for (i = 0; i < idle_max_cpu; ++i) { 2520 + struct idle_thread_runtime *itr; 2521 + 2522 + t = idle_threads[i]; 2523 + if (!t) 2524 + continue; 2525 + 2526 + itr = thread__priv(t); 2527 + if (itr == NULL) 2528 + continue; 2529 + 2530 + callchain_param.sort(&itr->sorted_root, &itr->callchain, 2531 + 0, &callchain_param); 2532 + 2533 + printf(" CPU %2d:", i); 2534 + print_sched_time(itr->tr.total_run_time, 6); 2535 + printf(" msec\n"); 2536 + timehist_print_idlehist_callchain(&itr->sorted_root); 2537 + printf("\n"); 2538 + } 2671 2539 } 2672 2540 2673 2541 printf("\n" ··· 3226 3036 OPT_BOOLEAN('w', "wakeups", &sched.show_wakeups, "Show wakeup events"), 3227 3037 OPT_BOOLEAN('M', "migrations", &sched.show_migrations, "Show migration events"), 3228 3038 OPT_BOOLEAN('V', "cpu-visual", &sched.show_cpu_visual, "Add CPU visual"), 3039 + OPT_BOOLEAN('I', "idle-hist", &sched.idle_hist, "Show idle events only"), 3229 3040 OPT_STRING(0, "time", &sched.time_str, "str", 3230 3041 "Time span for analysis (start,stop)"), 3231 3042 OPT_PARENT(sched_options)
+3 -3
tools/perf/builtin-stat.c
··· 2195 2195 } 2196 2196 2197 2197 static 2198 - int process_stat_config_event(struct perf_tool *tool __maybe_unused, 2198 + int process_stat_config_event(struct perf_tool *tool, 2199 2199 union perf_event *event, 2200 2200 struct perf_session *session __maybe_unused) 2201 2201 { ··· 2238 2238 } 2239 2239 2240 2240 static 2241 - int process_thread_map_event(struct perf_tool *tool __maybe_unused, 2241 + int process_thread_map_event(struct perf_tool *tool, 2242 2242 union perf_event *event, 2243 2243 struct perf_session *session __maybe_unused) 2244 2244 { ··· 2257 2257 } 2258 2258 2259 2259 static 2260 - int process_cpu_map_event(struct perf_tool *tool __maybe_unused, 2260 + int process_cpu_map_event(struct perf_tool *tool, 2261 2261 union perf_event *event, 2262 2262 struct perf_session *session __maybe_unused) 2263 2263 {
+59
tools/perf/check-headers.sh
··· 1 + #!/bin/sh 2 + 3 + HEADERS=' 4 + include/uapi/linux/perf_event.h 5 + include/linux/hash.h 6 + include/uapi/linux/hw_breakpoint.h 7 + arch/x86/include/asm/disabled-features.h 8 + arch/x86/include/asm/required-features.h 9 + arch/x86/include/asm/cpufeatures.h 10 + arch/arm/include/uapi/asm/perf_regs.h 11 + arch/arm64/include/uapi/asm/perf_regs.h 12 + arch/powerpc/include/uapi/asm/perf_regs.h 13 + arch/x86/include/uapi/asm/perf_regs.h 14 + arch/x86/include/uapi/asm/kvm.h 15 + arch/x86/include/uapi/asm/kvm_perf.h 16 + arch/x86/include/uapi/asm/svm.h 17 + arch/x86/include/uapi/asm/vmx.h 18 + arch/powerpc/include/uapi/asm/kvm.h 19 + arch/s390/include/uapi/asm/kvm.h 20 + arch/s390/include/uapi/asm/kvm_perf.h 21 + arch/s390/include/uapi/asm/sie.h 22 + arch/arm/include/uapi/asm/kvm.h 23 + arch/arm64/include/uapi/asm/kvm.h 24 + include/asm-generic/bitops/arch_hweight.h 25 + include/asm-generic/bitops/const_hweight.h 26 + include/asm-generic/bitops/__fls.h 27 + include/asm-generic/bitops/fls.h 28 + include/asm-generic/bitops/fls64.h 29 + include/linux/coresight-pmu.h 30 + include/uapi/asm-generic/mman-common.h 31 + ' 32 + 33 + check () { 34 + file=$1 35 + opts= 36 + 37 + shift 38 + while [ -n "$*" ]; do 39 + opts="$opts \"$1\"" 40 + shift 41 + done 42 + 43 + cmd="diff $opts ../$file ../../$file > /dev/null" 44 + 45 + test -f ../../$file && 46 + eval $cmd || echo "Warning: $file differs from kernel" >&2 47 + } 48 + 49 + 50 + # simple diff check 51 + for i in $HEADERS; do 52 + check $i -B 53 + done 54 + 55 + # diff with extra ignore lines 56 + check arch/x86/lib/memcpy_64.S -B -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" 57 + check arch/x86/lib/memset_64.S -B -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" 58 + check include/uapi/asm-generic/mman.h -B -I "^#include <\(uapi/\)*asm-generic/mman-common.h>" 59 + check include/uapi/linux/mman.h -B -I "^#include <\(uapi/\)*asm/mman.h>"
+1
tools/perf/perf.h
··· 55 55 bool all_user; 56 56 bool tail_synthesize; 57 57 bool overwrite; 58 + bool ignore_missing_thread; 58 59 unsigned int freq; 59 60 unsigned int mmap_pages; 60 61 unsigned int auxtrace_mmap_pages;
+4
tools/perf/tests/builtin-test.c
··· 186 186 .func = test__thread_map_synthesize, 187 187 }, 188 188 { 189 + .desc = "Remove thread map", 190 + .func = test__thread_map_remove, 191 + }, 192 + { 189 193 .desc = "Synthesize cpu map", 190 194 .func = test__cpu_map_synthesize, 191 195 },
+1
tools/perf/tests/tests.h
··· 80 80 int test__bpf_subtest_get_nr(void); 81 81 int test_session_topology(int subtest); 82 82 int test__thread_map_synthesize(int subtest); 83 + int test__thread_map_remove(int subtest); 83 84 int test__cpu_map_synthesize(int subtest); 84 85 int test__synthesize_stat_config(int subtest); 85 86 int test__synthesize_stat(int subtest);
+44
tools/perf/tests/thread-map.c
··· 1 + #include <stdlib.h> 1 2 #include <sys/types.h> 2 3 #include <unistd.h> 3 4 #include <sys/prctl.h> ··· 92 91 TEST_ASSERT_VAL("failed to synthesize map", 93 92 !perf_event__synthesize_thread_map2(NULL, threads, process_event, NULL)); 94 93 94 + return 0; 95 + } 96 + 97 + int test__thread_map_remove(int subtest __maybe_unused) 98 + { 99 + struct thread_map *threads; 100 + char *str; 101 + int i; 102 + 103 + TEST_ASSERT_VAL("failed to allocate map string", 104 + asprintf(&str, "%d,%d", getpid(), getppid()) >= 0); 105 + 106 + threads = thread_map__new_str(str, NULL, 0); 107 + 108 + TEST_ASSERT_VAL("failed to allocate thread_map", 109 + threads); 110 + 111 + if (verbose) 112 + thread_map__fprintf(threads, stderr); 113 + 114 + TEST_ASSERT_VAL("failed to remove thread", 115 + !thread_map__remove(threads, 0)); 116 + 117 + TEST_ASSERT_VAL("thread_map count != 1", threads->nr == 1); 118 + 119 + if (verbose) 120 + thread_map__fprintf(threads, stderr); 121 + 122 + TEST_ASSERT_VAL("failed to remove thread", 123 + !thread_map__remove(threads, 0)); 124 + 125 + TEST_ASSERT_VAL("thread_map count != 0", threads->nr == 0); 126 + 127 + if (verbose) 128 + thread_map__fprintf(threads, stderr); 129 + 130 + TEST_ASSERT_VAL("failed to not remove thread", 131 + thread_map__remove(threads, 0)); 132 + 133 + for (i = 0; i < threads->nr; i++) 134 + free(threads->map[i].comm); 135 + 136 + free(threads); 95 137 return 0; 96 138 }
+2
tools/perf/trace/beauty/mmap.c
··· 42 42 43 43 P_MMAP_FLAG(SHARED); 44 44 P_MMAP_FLAG(PRIVATE); 45 + #ifdef MAP_32BIT 45 46 P_MMAP_FLAG(32BIT); 47 + #endif 46 48 P_MMAP_FLAG(ANONYMOUS); 47 49 P_MMAP_FLAG(DENYWRITE); 48 50 P_MMAP_FLAG(EXECUTABLE);
+3 -2
tools/perf/ui/browsers/annotate.c
··· 215 215 ui_browser__set_color(browser, color); 216 216 if (dl->ins.ops && dl->ins.ops->scnprintf) { 217 217 if (ins__is_jump(&dl->ins)) { 218 - bool fwd = dl->ops.target.offset > (u64)dl->offset; 218 + bool fwd = dl->ops.target.offset > dl->offset; 219 219 220 220 ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR : 221 221 SLSMG_UARROW_CHAR); ··· 245 245 { 246 246 if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins) 247 247 || !disasm_line__has_offset(dl) 248 - || dl->ops.target.offset >= symbol__size(sym)) 248 + || dl->ops.target.offset < 0 249 + || dl->ops.target.offset >= (s64)symbol__size(sym)) 249 250 return false; 250 251 251 252 return true;
+17 -8
tools/perf/util/annotate.c
··· 223 223 static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map *map __maybe_unused) 224 224 { 225 225 const char *s = strchr(ops->raw, '+'); 226 + const char *c = strchr(ops->raw, ','); 226 227 227 - ops->target.addr = strtoull(ops->raw, NULL, 16); 228 - 229 - if (s++ != NULL) 230 - ops->target.offset = strtoull(s, NULL, 16); 228 + if (c++ != NULL) 229 + ops->target.addr = strtoull(c, NULL, 16); 231 230 else 232 - ops->target.offset = UINT64_MAX; 231 + ops->target.addr = strtoull(ops->raw, NULL, 16); 232 + 233 + if (s++ != NULL) { 234 + ops->target.offset = strtoull(s, NULL, 16); 235 + ops->target.offset_avail = true; 236 + } else { 237 + ops->target.offset_avail = false; 238 + } 233 239 234 240 return 0; 235 241 } ··· 243 237 static int jump__scnprintf(struct ins *ins, char *bf, size_t size, 244 238 struct ins_operands *ops) 245 239 { 246 - if (!ops->target.addr) 240 + if (!ops->target.addr || ops->target.offset < 0) 247 241 return ins__raw_scnprintf(ins, bf, size, ops); 248 242 249 243 return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset); ··· 647 641 648 642 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); 649 643 650 - if (addr < sym->start || addr >= sym->end) { 644 + if ((addr < sym->start || addr >= sym->end) && 645 + (addr != sym->end || sym->start != sym->end)) { 651 646 pr_debug("%s(%d): ERANGE! sym->name=%s, start=%#" PRIx64 ", addr=%#" PRIx64 ", end=%#" PRIx64 "\n", 652 647 __func__, __LINE__, sym->name, sym->start, addr, sym->end); 653 648 return -ERANGE; ··· 1212 1205 if (dl == NULL) 1213 1206 return -1; 1214 1207 1215 - if (dl->ops.target.offset == UINT64_MAX) 1208 + if (!disasm_line__has_offset(dl)) { 1216 1209 dl->ops.target.offset = dl->ops.target.addr - 1217 1210 map__rip_2objdump(map, sym->start); 1211 + dl->ops.target.offset_avail = true; 1212 + } 1218 1213 1219 1214 /* kcore has no symbols, so add the call target name */ 1220 1215 if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.name) {
+3 -2
tools/perf/util/annotate.h
··· 24 24 char *raw; 25 25 char *name; 26 26 u64 addr; 27 - u64 offset; 27 + s64 offset; 28 + bool offset_avail; 28 29 } target; 29 30 union { 30 31 struct { ··· 69 68 70 69 static inline bool disasm_line__has_offset(const struct disasm_line *dl) 71 70 { 72 - return dl->ops.target.offset != UINT64_MAX; 71 + return dl->ops.target.offset_avail; 73 72 } 74 73 75 74 void disasm_line__free(struct disasm_line *dl);
+53 -8
tools/perf/util/evsel.c
··· 990 990 * it overloads any global configuration. 991 991 */ 992 992 apply_config_terms(evsel, opts); 993 + 994 + evsel->ignore_missing_thread = opts->ignore_missing_thread; 993 995 } 994 996 995 997 static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) ··· 1421 1419 return fprintf(fp, " %-32s %s\n", name, val); 1422 1420 } 1423 1421 1422 + static bool ignore_missing_thread(struct perf_evsel *evsel, 1423 + struct thread_map *threads, 1424 + int thread, int err) 1425 + { 1426 + if (!evsel->ignore_missing_thread) 1427 + return false; 1428 + 1429 + /* The system wide setup does not work with threads. */ 1430 + if (evsel->system_wide) 1431 + return false; 1432 + 1433 + /* The -ESRCH is perf event syscall errno for pid's not found. */ 1434 + if (err != -ESRCH) 1435 + return false; 1436 + 1437 + /* If there's only one thread, let it fail. */ 1438 + if (threads->nr == 1) 1439 + return false; 1440 + 1441 + if (thread_map__remove(threads, thread)) 1442 + return false; 1443 + 1444 + pr_warning("WARNING: Ignored open failure for pid %d\n", 1445 + thread_map__pid(threads, thread)); 1446 + return true; 1447 + } 1448 + 1424 1449 static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 1425 1450 struct thread_map *threads) 1426 1451 { ··· 1503 1474 for (cpu = 0; cpu < cpus->nr; cpu++) { 1504 1475 1505 1476 for (thread = 0; thread < nthreads; thread++) { 1506 - int group_fd; 1477 + int fd, group_fd; 1507 1478 1508 1479 if (!evsel->cgrp && !evsel->system_wide) 1509 1480 pid = thread_map__pid(threads, thread); ··· 1513 1484 pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx", 1514 1485 pid, cpus->map[cpu], group_fd, flags); 1515 1486 1516 - FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr, 1517 - pid, 1518 - cpus->map[cpu], 1519 - group_fd, flags); 1520 - if (FD(evsel, cpu, thread) < 0) { 1487 + fd = sys_perf_event_open(&evsel->attr, pid, cpus->map[cpu], 1488 + group_fd, flags); 1489 + 1490 + FD(evsel, cpu, thread) = fd; 1491 + 1492 + if (fd < 0) { 1521 1493 err = -errno; 1494 + 1495 + if (ignore_missing_thread(evsel, threads, thread, err)) { 1496 + /* 1497 + * We just removed 1 thread, so take a step 1498 + * back on thread index and lower the upper 1499 + * nthreads limit. 1500 + */ 1501 + nthreads--; 1502 + thread--; 1503 + 1504 + /* ... and pretend like nothing have happened. */ 1505 + err = 0; 1506 + continue; 1507 + } 1508 + 1522 1509 pr_debug2("\nsys_perf_event_open failed, error %d\n", 1523 1510 err); 1524 1511 goto try_fallback; 1525 1512 } 1526 1513 1527 - pr_debug2(" = %d\n", FD(evsel, cpu, thread)); 1514 + pr_debug2(" = %d\n", fd); 1528 1515 1529 1516 if (evsel->bpf_fd >= 0) { 1530 - int evt_fd = FD(evsel, cpu, thread); 1517 + int evt_fd = fd; 1531 1518 int bpf_fd = evsel->bpf_fd; 1532 1519 1533 1520 err = ioctl(evt_fd,
+1
tools/perf/util/evsel.h
··· 120 120 bool tracking; 121 121 bool per_pkg; 122 122 bool precise_max; 123 + bool ignore_missing_thread; 123 124 /* parse modifier helper */ 124 125 int exclude_GH; 125 126 int nr_members;
+2 -1
tools/perf/util/symbol.c
··· 1459 1459 * Read the build id if possible. This is required for 1460 1460 * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work 1461 1461 */ 1462 - if (is_regular_file(dso->long_name) && 1462 + if (!dso->has_build_id && 1463 + is_regular_file(dso->long_name) && 1463 1464 filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0) 1464 1465 dso__set_build_id(dso, build_id); 1465 1466
+22
tools/perf/util/thread_map.c
··· 448 448 449 449 return false; 450 450 } 451 + 452 + int thread_map__remove(struct thread_map *threads, int idx) 453 + { 454 + int i; 455 + 456 + if (threads->nr < 1) 457 + return -EINVAL; 458 + 459 + if (idx >= threads->nr) 460 + return -EINVAL; 461 + 462 + /* 463 + * Free the 'idx' item and shift the rest up. 464 + */ 465 + free(threads->map[idx].comm); 466 + 467 + for (i = idx; i < threads->nr - 1; i++) 468 + threads->map[i] = threads->map[i + 1]; 469 + 470 + threads->nr--; 471 + return 0; 472 + }
+1
tools/perf/util/thread_map.h
··· 58 58 59 59 void thread_map__read_comms(struct thread_map *threads); 60 60 bool thread_map__has(struct thread_map *threads, pid_t pid); 61 + int thread_map__remove(struct thread_map *threads, int idx); 61 62 #endif /* __PERF_THREAD_MAP_H */