aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-12-23 19:49:12 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-12-23 19:49:12 -0500
commit00198dab3b825ab264424a052beea5acb859754f (patch)
tree1afa5fc96a0447bc8049a9992e5d4d047f5f0b38 /tools
parent9004fda59577d439564d44d6d1db52d262fe3f99 (diff)
parent3705b97505bcbf6440f38119c0e7d6058f585b54 (diff)
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 ...
Diffstat (limited to 'tools')
-rw-r--r--tools/include/uapi/linux/bpf.h593
-rw-r--r--tools/lib/bpf/bpf.c30
-rw-r--r--tools/lib/bpf/bpf.h9
-rw-r--r--tools/lib/bpf/libbpf.c3
-rw-r--r--tools/perf/Documentation/perf-sched.txt4
-rw-r--r--tools/perf/Makefile.perf94
-rw-r--r--tools/perf/bench/futex-lock-pi.c2
-rw-r--r--tools/perf/builtin-c2c.c13
-rw-r--r--tools/perf/builtin-mem.c4
-rw-r--r--tools/perf/builtin-record.c3
-rw-r--r--tools/perf/builtin-report.c2
-rw-r--r--tools/perf/builtin-sched.c275
-rw-r--r--tools/perf/builtin-stat.c6
-rwxr-xr-xtools/perf/check-headers.sh59
-rw-r--r--tools/perf/perf.h1
-rw-r--r--tools/perf/tests/builtin-test.c4
-rw-r--r--tools/perf/tests/tests.h1
-rw-r--r--tools/perf/tests/thread-map.c44
-rw-r--r--tools/perf/trace/beauty/mmap.c2
-rw-r--r--tools/perf/ui/browsers/annotate.c5
-rw-r--r--tools/perf/util/annotate.c23
-rw-r--r--tools/perf/util/annotate.h5
-rw-r--r--tools/perf/util/evsel.c61
-rw-r--r--tools/perf/util/evsel.h1
-rw-r--r--tools/perf/util/symbol.c3
-rw-r--r--tools/perf/util/thread_map.c22
-rw-r--r--tools/perf/util/thread_map.h1
27 files changed, 865 insertions, 405 deletions
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 9e5fc168c8a3..0eb0e87dbe9f 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -73,6 +73,8 @@ enum bpf_cmd {
73 BPF_PROG_LOAD, 73 BPF_PROG_LOAD,
74 BPF_OBJ_PIN, 74 BPF_OBJ_PIN,
75 BPF_OBJ_GET, 75 BPF_OBJ_GET,
76 BPF_PROG_ATTACH,
77 BPF_PROG_DETACH,
76}; 78};
77 79
78enum bpf_map_type { 80enum bpf_map_type {
@@ -85,6 +87,8 @@ enum bpf_map_type {
85 BPF_MAP_TYPE_PERCPU_ARRAY, 87 BPF_MAP_TYPE_PERCPU_ARRAY,
86 BPF_MAP_TYPE_STACK_TRACE, 88 BPF_MAP_TYPE_STACK_TRACE,
87 BPF_MAP_TYPE_CGROUP_ARRAY, 89 BPF_MAP_TYPE_CGROUP_ARRAY,
90 BPF_MAP_TYPE_LRU_HASH,
91 BPF_MAP_TYPE_LRU_PERCPU_HASH,
88}; 92};
89 93
90enum bpf_prog_type { 94enum bpf_prog_type {
@@ -95,8 +99,23 @@ enum bpf_prog_type {
95 BPF_PROG_TYPE_SCHED_ACT, 99 BPF_PROG_TYPE_SCHED_ACT,
96 BPF_PROG_TYPE_TRACEPOINT, 100 BPF_PROG_TYPE_TRACEPOINT,
97 BPF_PROG_TYPE_XDP, 101 BPF_PROG_TYPE_XDP,
102 BPF_PROG_TYPE_PERF_EVENT,
103 BPF_PROG_TYPE_CGROUP_SKB,
104 BPF_PROG_TYPE_CGROUP_SOCK,
105 BPF_PROG_TYPE_LWT_IN,
106 BPF_PROG_TYPE_LWT_OUT,
107 BPF_PROG_TYPE_LWT_XMIT,
98}; 108};
99 109
110enum bpf_attach_type {
111 BPF_CGROUP_INET_INGRESS,
112 BPF_CGROUP_INET_EGRESS,
113 BPF_CGROUP_INET_SOCK_CREATE,
114 __MAX_BPF_ATTACH_TYPE
115};
116
117#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
118
100#define BPF_PSEUDO_MAP_FD 1 119#define BPF_PSEUDO_MAP_FD 1
101 120
102/* flags for BPF_MAP_UPDATE_ELEM command */ 121/* flags for BPF_MAP_UPDATE_ELEM command */
@@ -105,6 +124,13 @@ enum bpf_prog_type {
105#define BPF_EXIST 2 /* update existing element */ 124#define BPF_EXIST 2 /* update existing element */
106 125
107#define BPF_F_NO_PREALLOC (1U << 0) 126#define BPF_F_NO_PREALLOC (1U << 0)
127/* Instead of having one common LRU list in the
128 * BPF_MAP_TYPE_LRU_[PERCPU_]HASH map, use a percpu LRU list
129 * which can scale and perform better.
130 * Note, the LRU nodes (including free nodes) cannot be moved
131 * across different LRU lists.
132 */
133#define BPF_F_NO_COMMON_LRU (1U << 1)
108 134
109union bpf_attr { 135union bpf_attr {
110 struct { /* anonymous struct used by BPF_MAP_CREATE command */ 136 struct { /* anonymous struct used by BPF_MAP_CREATE command */
@@ -140,243 +166,327 @@ union bpf_attr {
140 __aligned_u64 pathname; 166 __aligned_u64 pathname;
141 __u32 bpf_fd; 167 __u32 bpf_fd;
142 }; 168 };
169
170 struct { /* anonymous struct used by BPF_PROG_ATTACH/DETACH commands */
171 __u32 target_fd; /* container object to attach to */
172 __u32 attach_bpf_fd; /* eBPF program to attach */
173 __u32 attach_type;
174 };
143} __attribute__((aligned(8))); 175} __attribute__((aligned(8)));
144 176
177/* BPF helper function descriptions:
178 *
179 * void *bpf_map_lookup_elem(&map, &key)
180 * Return: Map value or NULL
181 *
182 * int bpf_map_update_elem(&map, &key, &value, flags)
183 * Return: 0 on success or negative error
184 *
185 * int bpf_map_delete_elem(&map, &key)
186 * Return: 0 on success or negative error
187 *
188 * int bpf_probe_read(void *dst, int size, void *src)
189 * Return: 0 on success or negative error
190 *
191 * u64 bpf_ktime_get_ns(void)
192 * Return: current ktime
193 *
194 * int bpf_trace_printk(const char *fmt, int fmt_size, ...)
195 * Return: length of buffer written or negative error
196 *
197 * u32 bpf_prandom_u32(void)
198 * Return: random value
199 *
200 * u32 bpf_raw_smp_processor_id(void)
201 * Return: SMP processor ID
202 *
203 * int bpf_skb_store_bytes(skb, offset, from, len, flags)
204 * store bytes into packet
205 * @skb: pointer to skb
206 * @offset: offset within packet from skb->mac_header
207 * @from: pointer where to copy bytes from
208 * @len: number of bytes to store into packet
209 * @flags: bit 0 - if true, recompute skb->csum
210 * other bits - reserved
211 * Return: 0 on success or negative error
212 *
213 * int bpf_l3_csum_replace(skb, offset, from, to, flags)
214 * recompute IP checksum
215 * @skb: pointer to skb
216 * @offset: offset within packet where IP checksum is located
217 * @from: old value of header field
218 * @to: new value of header field
219 * @flags: bits 0-3 - size of header field
220 * other bits - reserved
221 * Return: 0 on success or negative error
222 *
223 * int bpf_l4_csum_replace(skb, offset, from, to, flags)
224 * recompute TCP/UDP checksum
225 * @skb: pointer to skb
226 * @offset: offset within packet where TCP/UDP checksum is located
227 * @from: old value of header field
228 * @to: new value of header field
229 * @flags: bits 0-3 - size of header field
230 * bit 4 - is pseudo header
231 * other bits - reserved
232 * Return: 0 on success or negative error
233 *
234 * int bpf_tail_call(ctx, prog_array_map, index)
235 * jump into another BPF program
236 * @ctx: context pointer passed to next program
237 * @prog_array_map: pointer to map which type is BPF_MAP_TYPE_PROG_ARRAY
238 * @index: index inside array that selects specific program to run
239 * Return: 0 on success or negative error
240 *
241 * int bpf_clone_redirect(skb, ifindex, flags)
242 * redirect to another netdev
243 * @skb: pointer to skb
244 * @ifindex: ifindex of the net device
245 * @flags: bit 0 - if set, redirect to ingress instead of egress
246 * other bits - reserved
247 * Return: 0 on success or negative error
248 *
249 * u64 bpf_get_current_pid_tgid(void)
250 * Return: current->tgid << 32 | current->pid
251 *
252 * u64 bpf_get_current_uid_gid(void)
253 * Return: current_gid << 32 | current_uid
254 *
255 * int bpf_get_current_comm(char *buf, int size_of_buf)
256 * stores current->comm into buf
257 * Return: 0 on success or negative error
258 *
259 * u32 bpf_get_cgroup_classid(skb)
260 * retrieve a proc's classid
261 * @skb: pointer to skb
262 * Return: classid if != 0
263 *
264 * int bpf_skb_vlan_push(skb, vlan_proto, vlan_tci)
265 * Return: 0 on success or negative error
266 *
267 * int bpf_skb_vlan_pop(skb)
268 * Return: 0 on success or negative error
269 *
270 * int bpf_skb_get_tunnel_key(skb, key, size, flags)
271 * int bpf_skb_set_tunnel_key(skb, key, size, flags)
272 * retrieve or populate tunnel metadata
273 * @skb: pointer to skb
274 * @key: pointer to 'struct bpf_tunnel_key'
275 * @size: size of 'struct bpf_tunnel_key'
276 * @flags: room for future extensions
277 * Return: 0 on success or negative error
278 *
279 * u64 bpf_perf_event_read(&map, index)
280 * Return: Number events read or error code
281 *
282 * int bpf_redirect(ifindex, flags)
283 * redirect to another netdev
284 * @ifindex: ifindex of the net device
285 * @flags: bit 0 - if set, redirect to ingress instead of egress
286 * other bits - reserved
287 * Return: TC_ACT_REDIRECT
288 *
289 * u32 bpf_get_route_realm(skb)
290 * retrieve a dst's tclassid
291 * @skb: pointer to skb
292 * Return: realm if != 0
293 *
294 * int bpf_perf_event_output(ctx, map, index, data, size)
295 * output perf raw sample
296 * @ctx: struct pt_regs*
297 * @map: pointer to perf_event_array map
298 * @index: index of event in the map
299 * @data: data on stack to be output as raw data
300 * @size: size of data
301 * Return: 0 on success or negative error
302 *
303 * int bpf_get_stackid(ctx, map, flags)
304 * walk user or kernel stack and return id
305 * @ctx: struct pt_regs*
306 * @map: pointer to stack_trace map
307 * @flags: bits 0-7 - numer of stack frames to skip
308 * bit 8 - collect user stack instead of kernel
309 * bit 9 - compare stacks by hash only
310 * bit 10 - if two different stacks hash into the same stackid
311 * discard old
312 * other bits - reserved
313 * Return: >= 0 stackid on success or negative error
314 *
315 * s64 bpf_csum_diff(from, from_size, to, to_size, seed)
316 * calculate csum diff
317 * @from: raw from buffer
318 * @from_size: length of from buffer
319 * @to: raw to buffer
320 * @to_size: length of to buffer
321 * @seed: optional seed
322 * Return: csum result or negative error code
323 *
324 * int bpf_skb_get_tunnel_opt(skb, opt, size)
325 * retrieve tunnel options metadata
326 * @skb: pointer to skb
327 * @opt: pointer to raw tunnel option data
328 * @size: size of @opt
329 * Return: option size
330 *
331 * int bpf_skb_set_tunnel_opt(skb, opt, size)
332 * populate tunnel options metadata
333 * @skb: pointer to skb
334 * @opt: pointer to raw tunnel option data
335 * @size: size of @opt
336 * Return: 0 on success or negative error
337 *
338 * int bpf_skb_change_proto(skb, proto, flags)
339 * Change protocol of the skb. Currently supported is v4 -> v6,
340 * v6 -> v4 transitions. The helper will also resize the skb. eBPF
341 * program is expected to fill the new headers via skb_store_bytes
342 * and lX_csum_replace.
343 * @skb: pointer to skb
344 * @proto: new skb->protocol type
345 * @flags: reserved
346 * Return: 0 on success or negative error
347 *
348 * int bpf_skb_change_type(skb, type)
349 * Change packet type of skb.
350 * @skb: pointer to skb
351 * @type: new skb->pkt_type type
352 * Return: 0 on success or negative error
353 *
354 * int bpf_skb_under_cgroup(skb, map, index)
355 * Check cgroup2 membership of skb
356 * @skb: pointer to skb
357 * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type
358 * @index: index of the cgroup in the bpf_map
359 * Return:
360 * == 0 skb failed the cgroup2 descendant test
361 * == 1 skb succeeded the cgroup2 descendant test
362 * < 0 error
363 *
364 * u32 bpf_get_hash_recalc(skb)
365 * Retrieve and possibly recalculate skb->hash.
366 * @skb: pointer to skb
367 * Return: hash
368 *
369 * u64 bpf_get_current_task(void)
370 * Returns current task_struct
371 * Return: current
372 *
373 * int bpf_probe_write_user(void *dst, void *src, int len)
374 * safely attempt to write to a location
375 * @dst: destination address in userspace
376 * @src: source address on stack
377 * @len: number of bytes to copy
378 * Return: 0 on success or negative error
379 *
380 * int bpf_current_task_under_cgroup(map, index)
381 * Check cgroup2 membership of current task
382 * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type
383 * @index: index of the cgroup in the bpf_map
384 * Return:
385 * == 0 current failed the cgroup2 descendant test
386 * == 1 current succeeded the cgroup2 descendant test
387 * < 0 error
388 *
389 * int bpf_skb_change_tail(skb, len, flags)
390 * The helper will resize the skb to the given new size, to be used f.e.
391 * with control messages.
392 * @skb: pointer to skb
393 * @len: new skb length
394 * @flags: reserved
395 * Return: 0 on success or negative error
396 *
397 * int bpf_skb_pull_data(skb, len)
398 * The helper will pull in non-linear data in case the skb is non-linear
399 * and not all of len are part of the linear section. Only needed for
400 * read/write with direct packet access.
401 * @skb: pointer to skb
402 * @len: len to make read/writeable
403 * Return: 0 on success or negative error
404 *
405 * s64 bpf_csum_update(skb, csum)
406 * Adds csum into skb->csum in case of CHECKSUM_COMPLETE.
407 * @skb: pointer to skb
408 * @csum: csum to add
409 * Return: csum on success or negative error
410 *
411 * void bpf_set_hash_invalid(skb)
412 * Invalidate current skb->hash.
413 * @skb: pointer to skb
414 *
415 * int bpf_get_numa_node_id()
416 * Return: Id of current NUMA node.
417 *
418 * int bpf_skb_change_head()
419 * Grows headroom of skb and adjusts MAC header offset accordingly.
420 * Will extends/reallocae as required automatically.
421 * May change skb data pointer and will thus invalidate any check
422 * performed for direct packet access.
423 * @skb: pointer to skb
424 * @len: length of header to be pushed in front
425 * @flags: Flags (unused for now)
426 * Return: 0 on success or negative error
427 *
428 * int bpf_xdp_adjust_head(xdp_md, delta)
429 * Adjust the xdp_md.data by delta
430 * @xdp_md: pointer to xdp_md
431 * @delta: An positive/negative integer to be added to xdp_md.data
432 * Return: 0 on success or negative on error
433 */
434#define __BPF_FUNC_MAPPER(FN) \
435 FN(unspec), \
436 FN(map_lookup_elem), \
437 FN(map_update_elem), \
438 FN(map_delete_elem), \
439 FN(probe_read), \
440 FN(ktime_get_ns), \
441 FN(trace_printk), \
442 FN(get_prandom_u32), \
443 FN(get_smp_processor_id), \
444 FN(skb_store_bytes), \
445 FN(l3_csum_replace), \
446 FN(l4_csum_replace), \
447 FN(tail_call), \
448 FN(clone_redirect), \
449 FN(get_current_pid_tgid), \
450 FN(get_current_uid_gid), \
451 FN(get_current_comm), \
452 FN(get_cgroup_classid), \
453 FN(skb_vlan_push), \
454 FN(skb_vlan_pop), \
455 FN(skb_get_tunnel_key), \
456 FN(skb_set_tunnel_key), \
457 FN(perf_event_read), \
458 FN(redirect), \
459 FN(get_route_realm), \
460 FN(perf_event_output), \
461 FN(skb_load_bytes), \
462 FN(get_stackid), \
463 FN(csum_diff), \
464 FN(skb_get_tunnel_opt), \
465 FN(skb_set_tunnel_opt), \
466 FN(skb_change_proto), \
467 FN(skb_change_type), \
468 FN(skb_under_cgroup), \
469 FN(get_hash_recalc), \
470 FN(get_current_task), \
471 FN(probe_write_user), \
472 FN(current_task_under_cgroup), \
473 FN(skb_change_tail), \
474 FN(skb_pull_data), \
475 FN(csum_update), \
476 FN(set_hash_invalid), \
477 FN(get_numa_node_id), \
478 FN(skb_change_head), \
479 FN(xdp_adjust_head),
480
145/* integer value in 'imm' field of BPF_CALL instruction selects which helper 481/* integer value in 'imm' field of BPF_CALL instruction selects which helper
146 * function eBPF program intends to call 482 * function eBPF program intends to call
147 */ 483 */
484#define __BPF_ENUM_FN(x) BPF_FUNC_ ## x
148enum bpf_func_id { 485enum bpf_func_id {
149 BPF_FUNC_unspec, 486 __BPF_FUNC_MAPPER(__BPF_ENUM_FN)
150 BPF_FUNC_map_lookup_elem, /* void *map_lookup_elem(&map, &key) */
151 BPF_FUNC_map_update_elem, /* int map_update_elem(&map, &key, &value, flags) */
152 BPF_FUNC_map_delete_elem, /* int map_delete_elem(&map, &key) */
153 BPF_FUNC_probe_read, /* int bpf_probe_read(void *dst, int size, void *src) */
154 BPF_FUNC_ktime_get_ns, /* u64 bpf_ktime_get_ns(void) */
155 BPF_FUNC_trace_printk, /* int bpf_trace_printk(const char *fmt, int fmt_size, ...) */
156 BPF_FUNC_get_prandom_u32, /* u32 prandom_u32(void) */
157 BPF_FUNC_get_smp_processor_id, /* u32 raw_smp_processor_id(void) */
158
159 /**
160 * skb_store_bytes(skb, offset, from, len, flags) - store bytes into packet
161 * @skb: pointer to skb
162 * @offset: offset within packet from skb->mac_header
163 * @from: pointer where to copy bytes from
164 * @len: number of bytes to store into packet
165 * @flags: bit 0 - if true, recompute skb->csum
166 * other bits - reserved
167 * Return: 0 on success
168 */
169 BPF_FUNC_skb_store_bytes,
170
171 /**
172 * l3_csum_replace(skb, offset, from, to, flags) - recompute IP checksum
173 * @skb: pointer to skb
174 * @offset: offset within packet where IP checksum is located
175 * @from: old value of header field
176 * @to: new value of header field
177 * @flags: bits 0-3 - size of header field
178 * other bits - reserved
179 * Return: 0 on success
180 */
181 BPF_FUNC_l3_csum_replace,
182
183 /**
184 * l4_csum_replace(skb, offset, from, to, flags) - recompute TCP/UDP checksum
185 * @skb: pointer to skb
186 * @offset: offset within packet where TCP/UDP checksum is located
187 * @from: old value of header field
188 * @to: new value of header field
189 * @flags: bits 0-3 - size of header field
190 * bit 4 - is pseudo header
191 * other bits - reserved
192 * Return: 0 on success
193 */
194 BPF_FUNC_l4_csum_replace,
195
196 /**
197 * bpf_tail_call(ctx, prog_array_map, index) - jump into another BPF program
198 * @ctx: context pointer passed to next program
199 * @prog_array_map: pointer to map which type is BPF_MAP_TYPE_PROG_ARRAY
200 * @index: index inside array that selects specific program to run
201 * Return: 0 on success
202 */
203 BPF_FUNC_tail_call,
204
205 /**
206 * bpf_clone_redirect(skb, ifindex, flags) - redirect to another netdev
207 * @skb: pointer to skb
208 * @ifindex: ifindex of the net device
209 * @flags: bit 0 - if set, redirect to ingress instead of egress
210 * other bits - reserved
211 * Return: 0 on success
212 */
213 BPF_FUNC_clone_redirect,
214
215 /**
216 * u64 bpf_get_current_pid_tgid(void)
217 * Return: current->tgid << 32 | current->pid
218 */
219 BPF_FUNC_get_current_pid_tgid,
220
221 /**
222 * u64 bpf_get_current_uid_gid(void)
223 * Return: current_gid << 32 | current_uid
224 */
225 BPF_FUNC_get_current_uid_gid,
226
227 /**
228 * bpf_get_current_comm(char *buf, int size_of_buf)
229 * stores current->comm into buf
230 * Return: 0 on success
231 */
232 BPF_FUNC_get_current_comm,
233
234 /**
235 * bpf_get_cgroup_classid(skb) - retrieve a proc's classid
236 * @skb: pointer to skb
237 * Return: classid if != 0
238 */
239 BPF_FUNC_get_cgroup_classid,
240 BPF_FUNC_skb_vlan_push, /* bpf_skb_vlan_push(skb, vlan_proto, vlan_tci) */
241 BPF_FUNC_skb_vlan_pop, /* bpf_skb_vlan_pop(skb) */
242
243 /**
244 * bpf_skb_[gs]et_tunnel_key(skb, key, size, flags)
245 * retrieve or populate tunnel metadata
246 * @skb: pointer to skb
247 * @key: pointer to 'struct bpf_tunnel_key'
248 * @size: size of 'struct bpf_tunnel_key'
249 * @flags: room for future extensions
250 * Retrun: 0 on success
251 */
252 BPF_FUNC_skb_get_tunnel_key,
253 BPF_FUNC_skb_set_tunnel_key,
254 BPF_FUNC_perf_event_read, /* u64 bpf_perf_event_read(&map, index) */
255 /**
256 * bpf_redirect(ifindex, flags) - redirect to another netdev
257 * @ifindex: ifindex of the net device
258 * @flags: bit 0 - if set, redirect to ingress instead of egress
259 * other bits - reserved
260 * Return: TC_ACT_REDIRECT
261 */
262 BPF_FUNC_redirect,
263
264 /**
265 * bpf_get_route_realm(skb) - retrieve a dst's tclassid
266 * @skb: pointer to skb
267 * Return: realm if != 0
268 */
269 BPF_FUNC_get_route_realm,
270
271 /**
272 * bpf_perf_event_output(ctx, map, index, data, size) - output perf raw sample
273 * @ctx: struct pt_regs*
274 * @map: pointer to perf_event_array map
275 * @index: index of event in the map
276 * @data: data on stack to be output as raw data
277 * @size: size of data
278 * Return: 0 on success
279 */
280 BPF_FUNC_perf_event_output,
281 BPF_FUNC_skb_load_bytes,
282
283 /**
284 * bpf_get_stackid(ctx, map, flags) - walk user or kernel stack and return id
285 * @ctx: struct pt_regs*
286 * @map: pointer to stack_trace map
287 * @flags: bits 0-7 - numer of stack frames to skip
288 * bit 8 - collect user stack instead of kernel
289 * bit 9 - compare stacks by hash only
290 * bit 10 - if two different stacks hash into the same stackid
291 * discard old
292 * other bits - reserved
293 * Return: >= 0 stackid on success or negative error
294 */
295 BPF_FUNC_get_stackid,
296
297 /**
298 * bpf_csum_diff(from, from_size, to, to_size, seed) - calculate csum diff
299 * @from: raw from buffer
300 * @from_size: length of from buffer
301 * @to: raw to buffer
302 * @to_size: length of to buffer
303 * @seed: optional seed
304 * Return: csum result
305 */
306 BPF_FUNC_csum_diff,
307
308 /**
309 * bpf_skb_[gs]et_tunnel_opt(skb, opt, size)
310 * retrieve or populate tunnel options metadata
311 * @skb: pointer to skb
312 * @opt: pointer to raw tunnel option data
313 * @size: size of @opt
314 * Return: 0 on success for set, option size for get
315 */
316 BPF_FUNC_skb_get_tunnel_opt,
317 BPF_FUNC_skb_set_tunnel_opt,
318
319 /**
320 * bpf_skb_change_proto(skb, proto, flags)
321 * Change protocol of the skb. Currently supported is
322 * v4 -> v6, v6 -> v4 transitions. The helper will also
323 * resize the skb. eBPF program is expected to fill the
324 * new headers via skb_store_bytes and lX_csum_replace.
325 * @skb: pointer to skb
326 * @proto: new skb->protocol type
327 * @flags: reserved
328 * Return: 0 on success or negative error
329 */
330 BPF_FUNC_skb_change_proto,
331
332 /**
333 * bpf_skb_change_type(skb, type)
334 * Change packet type of skb.
335 * @skb: pointer to skb
336 * @type: new skb->pkt_type type
337 * Return: 0 on success or negative error
338 */
339 BPF_FUNC_skb_change_type,
340
341 /**
342 * bpf_skb_under_cgroup(skb, map, index) - Check cgroup2 membership of skb
343 * @skb: pointer to skb
344 * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type
345 * @index: index of the cgroup in the bpf_map
346 * Return:
347 * == 0 skb failed the cgroup2 descendant test
348 * == 1 skb succeeded the cgroup2 descendant test
349 * < 0 error
350 */
351 BPF_FUNC_skb_under_cgroup,
352
353 /**
354 * bpf_get_hash_recalc(skb)
355 * Retrieve and possibly recalculate skb->hash.
356 * @skb: pointer to skb
357 * Return: hash
358 */
359 BPF_FUNC_get_hash_recalc,
360
361 /**
362 * u64 bpf_get_current_task(void)
363 * Returns current task_struct
364 * Return: current
365 */
366 BPF_FUNC_get_current_task,
367
368 /**
369 * bpf_probe_write_user(void *dst, void *src, int len)
370 * safely attempt to write to a location
371 * @dst: destination address in userspace
372 * @src: source address on stack
373 * @len: number of bytes to copy
374 * Return: 0 on success or negative error
375 */
376 BPF_FUNC_probe_write_user,
377
378 __BPF_FUNC_MAX_ID, 487 __BPF_FUNC_MAX_ID,
379}; 488};
489#undef __BPF_ENUM_FN
380 490
381/* All flags used by eBPF helper functions, placed here. */ 491/* All flags used by eBPF helper functions, placed here. */
382 492
@@ -450,6 +560,31 @@ struct bpf_tunnel_key {
450 __u32 tunnel_label; 560 __u32 tunnel_label;
451}; 561};
452 562
563/* Generic BPF return codes which all BPF program types may support.
564 * The values are binary compatible with their TC_ACT_* counter-part to
565 * provide backwards compatibility with existing SCHED_CLS and SCHED_ACT
566 * programs.
567 *
568 * XDP is handled seprately, see XDP_*.
569 */
570enum bpf_ret_code {
571 BPF_OK = 0,
572 /* 1 reserved */
573 BPF_DROP = 2,
574 /* 3-6 reserved */
575 BPF_REDIRECT = 7,
576 /* >127 are reserved for prog type specific return codes */
577};
578
579struct bpf_sock {
580 __u32 bound_dev_if;
581 __u32 family;
582 __u32 type;
583 __u32 protocol;
584};
585
586#define XDP_PACKET_HEADROOM 256
587
453/* User return codes for XDP prog type. 588/* User return codes for XDP prog type.
454 * A valid XDP program must return one of these defined values. All other 589 * A valid XDP program must return one of these defined values. All other
455 * return codes are reserved for future use. Unknown return codes will result 590 * return codes are reserved for future use. Unknown return codes will result
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 8143536b462a..3ddb58a36d3c 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -54,7 +54,7 @@ static int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
54} 54}
55 55
56int bpf_create_map(enum bpf_map_type map_type, int key_size, 56int 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 union bpf_attr attr; 59 union bpf_attr attr;
60 60
@@ -64,13 +64,14 @@ int bpf_create_map(enum bpf_map_type map_type, int key_size,
64 attr.key_size = key_size; 64 attr.key_size = key_size;
65 attr.value_size = value_size; 65 attr.value_size = value_size;
66 attr.max_entries = max_entries; 66 attr.max_entries = max_entries;
67 attr.map_flags = map_flags;
67 68
68 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); 69 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
69} 70}
70 71
71int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns, 72int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns,
72 size_t insns_cnt, char *license, 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 int fd; 76 int fd;
76 union bpf_attr attr; 77 union bpf_attr attr;
@@ -98,7 +99,7 @@ int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns,
98} 99}
99 100
100int bpf_map_update_elem(int fd, void *key, void *value, 101int bpf_map_update_elem(int fd, void *key, void *value,
101 u64 flags) 102 __u64 flags)
102{ 103{
103 union bpf_attr attr; 104 union bpf_attr attr;
104 105
@@ -166,3 +167,26 @@ int bpf_obj_get(const char *pathname)
166 167
167 return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr)); 168 return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr));
168} 169}
170
171int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type)
172{
173 union bpf_attr attr;
174
175 bzero(&attr, sizeof(attr));
176 attr.target_fd = target_fd;
177 attr.attach_bpf_fd = prog_fd;
178 attr.attach_type = type;
179
180 return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
181}
182
183int bpf_prog_detach(int target_fd, enum bpf_attach_type type)
184{
185 union bpf_attr attr;
186
187 bzero(&attr, sizeof(attr));
188 attr.target_fd = target_fd;
189 attr.attach_type = type;
190
191 return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
192}
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 253c3dbb06b4..a2f9853dd882 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -24,22 +24,25 @@
24#include <linux/bpf.h> 24#include <linux/bpf.h>
25 25
26int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, 26int 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/* Recommend log buffer size */ 29/* Recommend log buffer size */
30#define BPF_LOG_BUF_SIZE 65536 30#define BPF_LOG_BUF_SIZE 65536
31int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns, 31int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns,
32 size_t insns_cnt, char *license, 32 size_t insns_cnt, char *license,
33 u32 kern_version, char *log_buf, 33 __u32 kern_version, char *log_buf,
34 size_t log_buf_sz); 34 size_t log_buf_sz);
35 35
36int bpf_map_update_elem(int fd, void *key, void *value, 36int bpf_map_update_elem(int fd, void *key, void *value,
37 u64 flags); 37 __u64 flags);
38 38
39int bpf_map_lookup_elem(int fd, void *key, void *value); 39int bpf_map_lookup_elem(int fd, void *key, void *value);
40int bpf_map_delete_elem(int fd, void *key); 40int bpf_map_delete_elem(int fd, void *key);
41int bpf_map_get_next_key(int fd, void *key, void *next_key); 41int bpf_map_get_next_key(int fd, void *key, void *next_key);
42int bpf_obj_pin(int fd, const char *pathname); 42int bpf_obj_pin(int fd, const char *pathname);
43int bpf_obj_get(const char *pathname); 43int bpf_obj_get(const char *pathname);
44int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type);
45int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
46
44 47
45#endif 48#endif
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 2e974593f3e8..84e6b35da4bd 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -854,7 +854,8 @@ bpf_object__create_maps(struct bpf_object *obj)
854 *pfd = bpf_create_map(def->type, 854 *pfd = bpf_create_map(def->type,
855 def->key_size, 855 def->key_size,
856 def->value_size, 856 def->value_size,
857 def->max_entries); 857 def->max_entries,
858 0);
858 if (*pfd < 0) { 859 if (*pfd < 0) {
859 size_t j; 860 size_t j;
860 int err = *pfd; 861 int err = *pfd;
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index 7775b1eb2bee..76173969ab80 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -132,6 +132,10 @@ OPTIONS for 'perf sched timehist'
132--migrations:: 132--migrations::
133 Show migration events. 133 Show migration events.
134 134
135-I::
136--idle-hist::
137 Show idle-related events only.
138
135--time:: 139--time::
136 Only analyze samples within given time window: <start>,<stop>. Times 140 Only analyze samples within given time window: <start>,<stop>. Times
137 have the format seconds.microseconds. If start is not given (i.e., time 141 have the format seconds.microseconds. If start is not given (i.e., time
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index e5af38eede17..8fc24824705e 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -201,6 +201,7 @@ goals := $(filter-out all sub-make, $(MAKECMDGOALS))
201$(goals) all: sub-make 201$(goals) all: sub-make
202 202
203sub-make: fixdep 203sub-make: fixdep
204 @./check-headers.sh
204 $(Q)$(MAKE) FIXDEP=1 -f Makefile.perf $(goals) 205 $(Q)$(MAKE) FIXDEP=1 -f Makefile.perf $(goals)
205 206
206else # force_fixdep 207else # force_fixdep
@@ -404,99 +405,6 @@ export JEVENTS
404build := -f $(srctree)/tools/build/Makefile.build dir=. obj 405build := -f $(srctree)/tools/build/Makefile.build dir=. obj
405 406
406$(PERF_IN): prepare FORCE 407$(PERF_IN): prepare FORCE
407 @(test -f ../../include/uapi/linux/perf_event.h && ( \
408 (diff -B ../include/uapi/linux/perf_event.h ../../include/uapi/linux/perf_event.h >/dev/null) \
409 || echo "Warning: tools/include/uapi/linux/perf_event.h differs from kernel" >&2 )) || true
410 @(test -f ../../include/linux/hash.h && ( \
411 (diff -B ../include/linux/hash.h ../../include/linux/hash.h >/dev/null) \
412 || echo "Warning: tools/include/linux/hash.h differs from kernel" >&2 )) || true
413 @(test -f ../../include/uapi/linux/hw_breakpoint.h && ( \
414 (diff -B ../include/uapi/linux/hw_breakpoint.h ../../include/uapi/linux/hw_breakpoint.h >/dev/null) \
415 || echo "Warning: tools/include/uapi/linux/hw_breakpoint.h differs from kernel" >&2 )) || true
416 @(test -f ../../arch/x86/include/asm/disabled-features.h && ( \
417 (diff -B ../arch/x86/include/asm/disabled-features.h ../../arch/x86/include/asm/disabled-features.h >/dev/null) \
418 || echo "Warning: tools/arch/x86/include/asm/disabled-features.h differs from kernel" >&2 )) || true
419 @(test -f ../../arch/x86/include/asm/required-features.h && ( \
420 (diff -B ../arch/x86/include/asm/required-features.h ../../arch/x86/include/asm/required-features.h >/dev/null) \
421 || echo "Warning: tools/arch/x86/include/asm/required-features.h differs from kernel" >&2 )) || true
422 @(test -f ../../arch/x86/include/asm/cpufeatures.h && ( \
423 (diff -B ../arch/x86/include/asm/cpufeatures.h ../../arch/x86/include/asm/cpufeatures.h >/dev/null) \
424 || echo "Warning: tools/arch/x86/include/asm/cpufeatures.h differs from kernel" >&2 )) || true
425 @(test -f ../../arch/x86/lib/memcpy_64.S && ( \
426 (diff -B -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" ../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memcpy_64.S >/dev/null) \
427 || echo "Warning: tools/arch/x86/lib/memcpy_64.S differs from kernel" >&2 )) || true
428 @(test -f ../../arch/x86/lib/memset_64.S && ( \
429 (diff -B -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" ../arch/x86/lib/memset_64.S ../../arch/x86/lib/memset_64.S >/dev/null) \
430 || echo "Warning: tools/arch/x86/lib/memset_64.S differs from kernel" >&2 )) || true
431 @(test -f ../../arch/arm/include/uapi/asm/perf_regs.h && ( \
432 (diff -B ../arch/arm/include/uapi/asm/perf_regs.h ../../arch/arm/include/uapi/asm/perf_regs.h >/dev/null) \
433 || echo "Warning: tools/arch/arm/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true
434 @(test -f ../../arch/arm64/include/uapi/asm/perf_regs.h && ( \
435 (diff -B ../arch/arm64/include/uapi/asm/perf_regs.h ../../arch/arm64/include/uapi/asm/perf_regs.h >/dev/null) \
436 || echo "Warning: tools/arch/arm64/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true
437 @(test -f ../../arch/powerpc/include/uapi/asm/perf_regs.h && ( \
438 (diff -B ../arch/powerpc/include/uapi/asm/perf_regs.h ../../arch/powerpc/include/uapi/asm/perf_regs.h >/dev/null) \
439 || echo "Warning: tools/arch/powerpc/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true
440 @(test -f ../../arch/x86/include/uapi/asm/perf_regs.h && ( \
441 (diff -B ../arch/x86/include/uapi/asm/perf_regs.h ../../arch/x86/include/uapi/asm/perf_regs.h >/dev/null) \
442 || echo "Warning: tools/arch/x86/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true
443 @(test -f ../../arch/x86/include/uapi/asm/kvm.h && ( \
444 (diff -B ../arch/x86/include/uapi/asm/kvm.h ../../arch/x86/include/uapi/asm/kvm.h >/dev/null) \
445 || echo "Warning: tools/arch/x86/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true
446 @(test -f ../../arch/x86/include/uapi/asm/kvm_perf.h && ( \
447 (diff -B ../arch/x86/include/uapi/asm/kvm_perf.h ../../arch/x86/include/uapi/asm/kvm_perf.h >/dev/null) \
448 || echo "Warning: tools/arch/x86/include/uapi/asm/kvm_perf.h differs from kernel" >&2 )) || true
449 @(test -f ../../arch/x86/include/uapi/asm/svm.h && ( \
450 (diff -B ../arch/x86/include/uapi/asm/svm.h ../../arch/x86/include/uapi/asm/svm.h >/dev/null) \
451 || echo "Warning: tools/arch/x86/include/uapi/asm/svm.h differs from kernel" >&2 )) || true
452 @(test -f ../../arch/x86/include/uapi/asm/vmx.h && ( \
453 (diff -B ../arch/x86/include/uapi/asm/vmx.h ../../arch/x86/include/uapi/asm/vmx.h >/dev/null) \
454 || echo "Warning: tools/arch/x86/include/uapi/asm/vmx.h differs from kernel" >&2 )) || true
455 @(test -f ../../arch/powerpc/include/uapi/asm/kvm.h && ( \
456 (diff -B ../arch/powerpc/include/uapi/asm/kvm.h ../../arch/powerpc/include/uapi/asm/kvm.h >/dev/null) \
457 || echo "Warning: tools/arch/powerpc/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true
458 @(test -f ../../arch/s390/include/uapi/asm/kvm.h && ( \
459 (diff -B ../arch/s390/include/uapi/asm/kvm.h ../../arch/s390/include/uapi/asm/kvm.h >/dev/null) \
460 || echo "Warning: tools/arch/s390/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true
461 @(test -f ../../arch/s390/include/uapi/asm/kvm_perf.h && ( \
462 (diff -B ../arch/s390/include/uapi/asm/kvm_perf.h ../../arch/s390/include/uapi/asm/kvm_perf.h >/dev/null) \
463 || echo "Warning: tools/arch/s390/include/uapi/asm/kvm_perf.h differs from kernel" >&2 )) || true
464 @(test -f ../../arch/s390/include/uapi/asm/sie.h && ( \
465 (diff -B ../arch/s390/include/uapi/asm/sie.h ../../arch/s390/include/uapi/asm/sie.h >/dev/null) \
466 || echo "Warning: tools/arch/s390/include/uapi/asm/sie.h differs from kernel" >&2 )) || true
467 @(test -f ../../arch/arm/include/uapi/asm/kvm.h && ( \
468 (diff -B ../arch/arm/include/uapi/asm/kvm.h ../../arch/arm/include/uapi/asm/kvm.h >/dev/null) \
469 || echo "Warning: tools/arch/arm/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true
470 @(test -f ../../arch/arm64/include/uapi/asm/kvm.h && ( \
471 (diff -B ../arch/arm64/include/uapi/asm/kvm.h ../../arch/arm64/include/uapi/asm/kvm.h >/dev/null) \
472 || echo "Warning: tools/arch/arm64/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true
473 @(test -f ../../include/asm-generic/bitops/arch_hweight.h && ( \
474 (diff -B ../include/asm-generic/bitops/arch_hweight.h ../../include/asm-generic/bitops/arch_hweight.h >/dev/null) \
475 || echo "Warning: tools/include/asm-generic/bitops/arch_hweight.h differs from kernel" >&2 )) || true
476 @(test -f ../../include/asm-generic/bitops/const_hweight.h && ( \
477 (diff -B ../include/asm-generic/bitops/const_hweight.h ../../include/asm-generic/bitops/const_hweight.h >/dev/null) \
478 || echo "Warning: tools/include/asm-generic/bitops/const_hweight.h differs from kernel" >&2 )) || true
479 @(test -f ../../include/asm-generic/bitops/__fls.h && ( \
480 (diff -B ../include/asm-generic/bitops/__fls.h ../../include/asm-generic/bitops/__fls.h >/dev/null) \
481 || echo "Warning: tools/include/asm-generic/bitops/__fls.h differs from kernel" >&2 )) || true
482 @(test -f ../../include/asm-generic/bitops/fls.h && ( \
483 (diff -B ../include/asm-generic/bitops/fls.h ../../include/asm-generic/bitops/fls.h >/dev/null) \
484 || echo "Warning: tools/include/asm-generic/bitops/fls.h differs from kernel" >&2 )) || true
485 @(test -f ../../include/asm-generic/bitops/fls64.h && ( \
486 (diff -B ../include/asm-generic/bitops/fls64.h ../../include/asm-generic/bitops/fls64.h >/dev/null) \
487 || echo "Warning: tools/include/asm-generic/bitops/fls64.h differs from kernel" >&2 )) || true
488 @(test -f ../../include/linux/coresight-pmu.h && ( \
489 (diff -B ../include/linux/coresight-pmu.h ../../include/linux/coresight-pmu.h >/dev/null) \
490 || echo "Warning: tools/include/linux/coresight-pmu.h differs from kernel" >&2 )) || true
491 @(test -f ../../include/uapi/asm-generic/mman-common.h && ( \
492 (diff -B ../include/uapi/asm-generic/mman-common.h ../../include/uapi/asm-generic/mman-common.h >/dev/null) \
493 || echo "Warning: tools/include/uapi/asm-generic/mman-common.h differs from kernel" >&2 )) || true
494 @(test -f ../../include/uapi/asm-generic/mman.h && ( \
495 (diff -B -I "^#include <\(uapi/\)*asm-generic/mman-common.h>$$" ../include/uapi/asm-generic/mman.h ../../include/uapi/asm-generic/mman.h >/dev/null) \
496 || echo "Warning: tools/include/uapi/asm-generic/mman.h differs from kernel" >&2 )) || true
497 @(test -f ../../include/uapi/linux/mman.h && ( \
498 (diff -B -I "^#include <\(uapi/\)*asm/mman.h>$$" ../include/uapi/linux/mman.h ../../include/uapi/linux/mman.h >/dev/null) \
499 || echo "Warning: tools/include/uapi/linux/mman.h differs from kernel" >&2 )) || true
500 $(Q)$(MAKE) $(build)=perf 408 $(Q)$(MAKE) $(build)=perf
501 409
502$(JEVENTS_IN): FORCE 410$(JEVENTS_IN): FORCE
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
index 465012b320ee..6d9d6c40a916 100644
--- a/tools/perf/bench/futex-lock-pi.c
+++ b/tools/perf/bench/futex-lock-pi.c
@@ -48,7 +48,7 @@ static const struct option options[] = {
48}; 48};
49 49
50static const char * const bench_futex_lock_pi_usage[] = { 50static const char * const bench_futex_lock_pi_usage[] = {
51 "perf bench futex requeue <options>", 51 "perf bench futex lock-pi <options>",
52 NULL 52 NULL
53}; 53};
54 54
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index 4b419631753d..f8ca7a4ebabc 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -208,7 +208,7 @@ static void compute_stats(struct c2c_hist_entry *c2c_he,
208static int process_sample_event(struct perf_tool *tool __maybe_unused, 208static int process_sample_event(struct perf_tool *tool __maybe_unused,
209 union perf_event *event, 209 union perf_event *event,
210 struct perf_sample *sample, 210 struct perf_sample *sample,
211 struct perf_evsel *evsel __maybe_unused, 211 struct perf_evsel *evsel,
212 struct machine *machine) 212 struct machine *machine)
213{ 213{
214 struct c2c_hists *c2c_hists = &c2c.hists; 214 struct c2c_hists *c2c_hists = &c2c.hists;
@@ -379,7 +379,7 @@ static int symbol_width(struct hists *hists, struct sort_entry *se)
379 379
380static int c2c_width(struct perf_hpp_fmt *fmt, 380static int c2c_width(struct perf_hpp_fmt *fmt,
381 struct perf_hpp *hpp __maybe_unused, 381 struct perf_hpp *hpp __maybe_unused,
382 struct hists *hists __maybe_unused) 382 struct hists *hists)
383{ 383{
384 struct c2c_fmt *c2c_fmt; 384 struct c2c_fmt *c2c_fmt;
385 struct c2c_dimension *dim; 385 struct c2c_dimension *dim;
@@ -1127,7 +1127,7 @@ MEAN_ENTRY(mean_lcl_entry, lcl_hitm);
1127MEAN_ENTRY(mean_load_entry, load); 1127MEAN_ENTRY(mean_load_entry, load);
1128 1128
1129static int 1129static int
1130cpucnt_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp, 1130cpucnt_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1131 struct hist_entry *he) 1131 struct hist_entry *he)
1132{ 1132{
1133 struct c2c_hist_entry *c2c_he; 1133 struct c2c_hist_entry *c2c_he;
@@ -1141,7 +1141,7 @@ cpucnt_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp,
1141} 1141}
1142 1142
1143static int 1143static int
1144cl_idx_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp, 1144cl_idx_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1145 struct hist_entry *he) 1145 struct hist_entry *he)
1146{ 1146{
1147 struct c2c_hist_entry *c2c_he; 1147 struct c2c_hist_entry *c2c_he;
@@ -1155,7 +1155,7 @@ cl_idx_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp,
1155} 1155}
1156 1156
1157static int 1157static int
1158cl_idx_empty_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp, 1158cl_idx_empty_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1159 struct hist_entry *he) 1159 struct hist_entry *he)
1160{ 1160{
1161 int width = c2c_width(fmt, hpp, he->hists); 1161 int width = c2c_width(fmt, hpp, he->hists);
@@ -1779,7 +1779,6 @@ static int c2c_hists__init(struct c2c_hists *hists,
1779 return hpp_list__parse(&hists->list, NULL, sort); 1779 return hpp_list__parse(&hists->list, NULL, sort);
1780} 1780}
1781 1781
1782__maybe_unused
1783static int c2c_hists__reinit(struct c2c_hists *c2c_hists, 1782static int c2c_hists__reinit(struct c2c_hists *c2c_hists,
1784 const char *output, 1783 const char *output,
1785 const char *sort) 1784 const char *sort)
@@ -2658,7 +2657,7 @@ out:
2658 return err; 2657 return err;
2659} 2658}
2660 2659
2661static int parse_record_events(const struct option *opt __maybe_unused, 2660static int parse_record_events(const struct option *opt,
2662 const char *str, int unset __maybe_unused) 2661 const char *str, int unset __maybe_unused)
2663{ 2662{
2664 bool *event_set = (bool *) opt->value; 2663 bool *event_set = (bool *) opt->value;
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index d1ce29be560e..cd7bc4d104e2 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -70,8 +70,8 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
70 OPT_UINTEGER(0, "ldlat", &perf_mem_events__loads_ldlat, "mem-loads latency"), 70 OPT_UINTEGER(0, "ldlat", &perf_mem_events__loads_ldlat, "mem-loads latency"),
71 OPT_INCR('v', "verbose", &verbose, 71 OPT_INCR('v', "verbose", &verbose,
72 "be more verbose (show counter open errors, etc)"), 72 "be more verbose (show counter open errors, etc)"),
73 OPT_BOOLEAN('U', "--all-user", &all_user, "collect only user 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"), 74 OPT_BOOLEAN('K', "all-kernel", &all_kernel, "collect only kernel level data"),
75 OPT_END() 75 OPT_END()
76 }; 76 };
77 77
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index fa26865364b6..74d6a035133a 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1687,6 +1687,9 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1687 goto out; 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 err = -ENOMEM; 1693 err = -ENOMEM;
1691 if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1694 if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
1692 usage_with_options(record_usage, record_options); 1695 usage_with_options(record_usage, record_options);
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index d2afbe4a240d..06cc759a4597 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -648,7 +648,7 @@ report_parse_ignore_callees_opt(const struct option *opt __maybe_unused,
648} 648}
649 649
650static int 650static int
651parse_branch_mode(const struct option *opt __maybe_unused, 651parse_branch_mode(const struct option *opt,
652 const char *str __maybe_unused, int unset) 652 const char *str __maybe_unused, int unset)
653{ 653{
654 int *branch_mode = opt->value; 654 int *branch_mode = opt->value;
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 1a3f1be93372..d53e706a6f17 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -200,6 +200,7 @@ struct perf_sched {
200 /* options for timehist command */ 200 /* options for timehist command */
201 bool summary; 201 bool summary;
202 bool summary_only; 202 bool summary_only;
203 bool idle_hist;
203 bool show_callchain; 204 bool show_callchain;
204 unsigned int max_stack; 205 unsigned int max_stack;
205 bool show_cpu_visual; 206 bool show_cpu_visual;
@@ -230,6 +231,15 @@ struct evsel_runtime {
230 u32 ncpu; /* highest cpu slot allocated */ 231 u32 ncpu; /* highest cpu slot allocated */
231}; 232};
232 233
234/* per cpu idle time data */
235struct idle_thread_runtime {
236 struct thread_runtime tr;
237 struct thread *last_thread;
238 struct rb_root sorted_root;
239 struct callchain_root callchain;
240 struct callchain_cursor cursor;
241};
242
233/* track idle times per cpu */ 243/* track idle times per cpu */
234static struct thread **idle_threads; 244static struct thread **idle_threads;
235static int idle_max_cpu; 245static int idle_max_cpu;
@@ -1765,7 +1775,7 @@ static u64 perf_evsel__get_time(struct perf_evsel *evsel, u32 cpu)
1765 return r->last_time[cpu]; 1775 return r->last_time[cpu];
1766} 1776}
1767 1777
1768static int comm_width = 20; 1778static int comm_width = 30;
1769 1779
1770static char *timehist_get_commstr(struct thread *thread) 1780static char *timehist_get_commstr(struct thread *thread)
1771{ 1781{
@@ -1807,7 +1817,7 @@ static void timehist_header(struct perf_sched *sched)
1807 printf(" "); 1817 printf(" ");
1808 } 1818 }
1809 1819
1810 printf(" %-20s %9s %9s %9s", 1820 printf(" %-*s %9s %9s %9s", comm_width,
1811 "task name", "wait time", "sch delay", "run time"); 1821 "task name", "wait time", "sch delay", "run time");
1812 1822
1813 printf("\n"); 1823 printf("\n");
@@ -1820,7 +1830,8 @@ static void timehist_header(struct perf_sched *sched)
1820 if (sched->show_cpu_visual) 1830 if (sched->show_cpu_visual)
1821 printf(" %*s ", ncpus, ""); 1831 printf(" %*s ", ncpus, "");
1822 1832
1823 printf(" %-20s %9s %9s %9s\n", "[tid/pid]", "(msec)", "(msec)", "(msec)"); 1833 printf(" %-*s %9s %9s %9s\n", comm_width,
1834 "[tid/pid]", "(msec)", "(msec)", "(msec)");
1824 1835
1825 /* 1836 /*
1826 * separator 1837 * separator
@@ -1830,7 +1841,7 @@ static void timehist_header(struct perf_sched *sched)
1830 if (sched->show_cpu_visual) 1841 if (sched->show_cpu_visual)
1831 printf(" %.*s ", ncpus, graph_dotted_line); 1842 printf(" %.*s ", ncpus, graph_dotted_line);
1832 1843
1833 printf(" %.20s %.9s %.9s %.9s", 1844 printf(" %.*s %.9s %.9s %.9s", comm_width,
1834 graph_dotted_line, graph_dotted_line, graph_dotted_line, 1845 graph_dotted_line, graph_dotted_line, graph_dotted_line,
1835 graph_dotted_line); 1846 graph_dotted_line);
1836 1847
@@ -1939,39 +1950,40 @@ static void timehist_update_runtime_stats(struct thread_runtime *r,
1939 r->total_run_time += r->dt_run; 1950 r->total_run_time += r->dt_run;
1940} 1951}
1941 1952
1942static bool is_idle_sample(struct perf_sched *sched, 1953static bool is_idle_sample(struct perf_sample *sample,
1943 struct perf_sample *sample, 1954 struct perf_evsel *evsel)
1944 struct perf_evsel *evsel,
1945 struct machine *machine)
1946{ 1955{
1947 struct thread *thread;
1948 struct callchain_cursor *cursor = &callchain_cursor;
1949
1950 /* pid 0 == swapper == idle task */ 1956 /* pid 0 == swapper == idle task */
1951 if (sample->pid == 0) 1957 if (strcmp(perf_evsel__name(evsel), "sched:sched_switch") == 0)
1952 return true; 1958 return perf_evsel__intval(evsel, sample, "prev_pid") == 0;
1953 1959
1954 if (strcmp(perf_evsel__name(evsel), "sched:sched_switch") == 0) { 1960 return sample->pid == 0;
1955 if (perf_evsel__intval(evsel, sample, "prev_pid") == 0) 1961}
1956 return true; 1962
1957 } 1963static void save_task_callchain(struct perf_sched *sched,
1964 struct perf_sample *sample,
1965 struct perf_evsel *evsel,
1966 struct machine *machine)
1967{
1968 struct callchain_cursor *cursor = &callchain_cursor;
1969 struct thread *thread;
1958 1970
1959 /* want main thread for process - has maps */ 1971 /* want main thread for process - has maps */
1960 thread = machine__findnew_thread(machine, sample->pid, sample->pid); 1972 thread = machine__findnew_thread(machine, sample->pid, sample->pid);
1961 if (thread == NULL) { 1973 if (thread == NULL) {
1962 pr_debug("Failed to get thread for pid %d.\n", sample->pid); 1974 pr_debug("Failed to get thread for pid %d.\n", sample->pid);
1963 return false; 1975 return;
1964 } 1976 }
1965 1977
1966 if (!symbol_conf.use_callchain || sample->callchain == NULL) 1978 if (!symbol_conf.use_callchain || sample->callchain == NULL)
1967 return false; 1979 return;
1968 1980
1969 if (thread__resolve_callchain(thread, cursor, evsel, sample, 1981 if (thread__resolve_callchain(thread, cursor, evsel, sample,
1970 NULL, NULL, sched->max_stack + 2) != 0) { 1982 NULL, NULL, sched->max_stack + 2) != 0) {
1971 if (verbose) 1983 if (verbose)
1972 error("Failed to resolve callchain. Skipping\n"); 1984 error("Failed to resolve callchain. Skipping\n");
1973 1985
1974 return false; 1986 return;
1975 } 1987 }
1976 1988
1977 callchain_cursor_commit(cursor); 1989 callchain_cursor_commit(cursor);
@@ -1994,8 +2006,24 @@ static bool is_idle_sample(struct perf_sched *sched,
1994 2006
1995 callchain_cursor_advance(cursor); 2007 callchain_cursor_advance(cursor);
1996 } 2008 }
2009}
2010
2011static int init_idle_thread(struct thread *thread)
2012{
2013 struct idle_thread_runtime *itr;
2014
2015 thread__set_comm(thread, idle_comm, 0);
2016
2017 itr = zalloc(sizeof(*itr));
2018 if (itr == NULL)
2019 return -ENOMEM;
1997 2020
1998 return false; 2021 init_stats(&itr->tr.run_stats);
2022 callchain_init(&itr->callchain);
2023 callchain_cursor_reset(&itr->cursor);
2024 thread__set_priv(thread, itr);
2025
2026 return 0;
1999} 2027}
2000 2028
2001/* 2029/*
@@ -2004,7 +2032,7 @@ static bool is_idle_sample(struct perf_sched *sched,
2004 */ 2032 */
2005static int init_idle_threads(int ncpu) 2033static int init_idle_threads(int ncpu)
2006{ 2034{
2007 int i; 2035 int i, ret;
2008 2036
2009 idle_threads = zalloc(ncpu * sizeof(struct thread *)); 2037 idle_threads = zalloc(ncpu * sizeof(struct thread *));
2010 if (!idle_threads) 2038 if (!idle_threads)
@@ -2018,7 +2046,9 @@ static int init_idle_threads(int ncpu)
2018 if (idle_threads[i] == NULL) 2046 if (idle_threads[i] == NULL)
2019 return -ENOMEM; 2047 return -ENOMEM;
2020 2048
2021 thread__set_comm(idle_threads[i], idle_comm, 0); 2049 ret = init_idle_thread(idle_threads[i]);
2050 if (ret < 0)
2051 return ret;
2022 } 2052 }
2023 2053
2024 return 0; 2054 return 0;
@@ -2065,14 +2095,23 @@ static struct thread *get_idle_thread(int cpu)
2065 idle_threads[cpu] = thread__new(0, 0); 2095 idle_threads[cpu] = thread__new(0, 0);
2066 2096
2067 if (idle_threads[cpu]) { 2097 if (idle_threads[cpu]) {
2068 idle_threads[cpu]->tid = 0; 2098 if (init_idle_thread(idle_threads[cpu]) < 0)
2069 thread__set_comm(idle_threads[cpu], idle_comm, 0); 2099 return NULL;
2070 } 2100 }
2071 } 2101 }
2072 2102
2073 return idle_threads[cpu]; 2103 return idle_threads[cpu];
2074} 2104}
2075 2105
2106static void save_idle_callchain(struct idle_thread_runtime *itr,
2107 struct perf_sample *sample)
2108{
2109 if (!symbol_conf.use_callchain || sample->callchain == NULL)
2110 return;
2111
2112 callchain_cursor__copy(&itr->cursor, &callchain_cursor);
2113}
2114
2076/* 2115/*
2077 * handle runtime stats saved per thread 2116 * handle runtime stats saved per thread
2078 */ 2117 */
@@ -2111,7 +2150,7 @@ static struct thread *timehist_get_thread(struct perf_sched *sched,
2111{ 2150{
2112 struct thread *thread; 2151 struct thread *thread;
2113 2152
2114 if (is_idle_sample(sched, sample, evsel, machine)) { 2153 if (is_idle_sample(sample, evsel)) {
2115 thread = get_idle_thread(sample->cpu); 2154 thread = get_idle_thread(sample->cpu);
2116 if (thread == NULL) 2155 if (thread == NULL)
2117 pr_err("Failed to get idle thread for cpu %d.\n", sample->cpu); 2156 pr_err("Failed to get idle thread for cpu %d.\n", sample->cpu);
@@ -2124,13 +2163,37 @@ static struct thread *timehist_get_thread(struct perf_sched *sched,
2124 pr_debug("Failed to get thread for tid %d. skipping sample.\n", 2163 pr_debug("Failed to get thread for tid %d. skipping sample.\n",
2125 sample->tid); 2164 sample->tid);
2126 } 2165 }
2166
2167 save_task_callchain(sched, sample, evsel, machine);
2168 if (sched->idle_hist) {
2169 struct thread *idle;
2170 struct idle_thread_runtime *itr;
2171
2172 idle = get_idle_thread(sample->cpu);
2173 if (idle == NULL) {
2174 pr_err("Failed to get idle thread for cpu %d.\n", sample->cpu);
2175 return NULL;
2176 }
2177
2178 itr = thread__priv(idle);
2179 if (itr == NULL)
2180 return NULL;
2181
2182 itr->last_thread = thread;
2183
2184 /* copy task callchain when entering to idle */
2185 if (perf_evsel__intval(evsel, sample, "next_pid") == 0)
2186 save_idle_callchain(itr, sample);
2187 }
2127 } 2188 }
2128 2189
2129 return thread; 2190 return thread;
2130} 2191}
2131 2192
2132static bool timehist_skip_sample(struct perf_sched *sched, 2193static bool timehist_skip_sample(struct perf_sched *sched,
2133 struct thread *thread) 2194 struct thread *thread,
2195 struct perf_evsel *evsel,
2196 struct perf_sample *sample)
2134{ 2197{
2135 bool rc = false; 2198 bool rc = false;
2136 2199
@@ -2139,10 +2202,19 @@ static bool timehist_skip_sample(struct perf_sched *sched,
2139 sched->skipped_samples++; 2202 sched->skipped_samples++;
2140 } 2203 }
2141 2204
2205 if (sched->idle_hist) {
2206 if (strcmp(perf_evsel__name(evsel), "sched:sched_switch"))
2207 rc = true;
2208 else if (perf_evsel__intval(evsel, sample, "prev_pid") != 0 &&
2209 perf_evsel__intval(evsel, sample, "next_pid") != 0)
2210 rc = true;
2211 }
2212
2142 return rc; 2213 return rc;
2143} 2214}
2144 2215
2145static void timehist_print_wakeup_event(struct perf_sched *sched, 2216static void timehist_print_wakeup_event(struct perf_sched *sched,
2217 struct perf_evsel *evsel,
2146 struct perf_sample *sample, 2218 struct perf_sample *sample,
2147 struct machine *machine, 2219 struct machine *machine,
2148 struct thread *awakened) 2220 struct thread *awakened)
@@ -2155,8 +2227,8 @@ static void timehist_print_wakeup_event(struct perf_sched *sched,
2155 return; 2227 return;
2156 2228
2157 /* show wakeup unless both awakee and awaker are filtered */ 2229 /* show wakeup unless both awakee and awaker are filtered */
2158 if (timehist_skip_sample(sched, thread) && 2230 if (timehist_skip_sample(sched, thread, evsel, sample) &&
2159 timehist_skip_sample(sched, awakened)) { 2231 timehist_skip_sample(sched, awakened, evsel, sample)) {
2160 return; 2232 return;
2161 } 2233 }
2162 2234
@@ -2201,7 +2273,7 @@ static int timehist_sched_wakeup_event(struct perf_tool *tool,
2201 /* show wakeups if requested */ 2273 /* show wakeups if requested */
2202 if (sched->show_wakeups && 2274 if (sched->show_wakeups &&
2203 !perf_time__skip_sample(&sched->ptime, sample->time)) 2275 !perf_time__skip_sample(&sched->ptime, sample->time))
2204 timehist_print_wakeup_event(sched, sample, machine, thread); 2276 timehist_print_wakeup_event(sched, evsel, sample, machine, thread);
2205 2277
2206 return 0; 2278 return 0;
2207} 2279}
@@ -2228,8 +2300,8 @@ static void timehist_print_migration_event(struct perf_sched *sched,
2228 if (thread == NULL) 2300 if (thread == NULL)
2229 return; 2301 return;
2230 2302
2231 if (timehist_skip_sample(sched, thread) && 2303 if (timehist_skip_sample(sched, thread, evsel, sample) &&
2232 timehist_skip_sample(sched, migrated)) { 2304 timehist_skip_sample(sched, migrated, evsel, sample)) {
2233 return; 2305 return;
2234 } 2306 }
2235 2307
@@ -2314,7 +2386,7 @@ static int timehist_sched_change_event(struct perf_tool *tool,
2314 goto out; 2386 goto out;
2315 } 2387 }
2316 2388
2317 if (timehist_skip_sample(sched, thread)) 2389 if (timehist_skip_sample(sched, thread, evsel, sample))
2318 goto out; 2390 goto out;
2319 2391
2320 tr = thread__get_runtime(thread); 2392 tr = thread__get_runtime(thread);
@@ -2333,7 +2405,7 @@ static int timehist_sched_change_event(struct perf_tool *tool,
2333 if (ptime->start && ptime->start > t) 2405 if (ptime->start && ptime->start > t)
2334 goto out; 2406 goto out;
2335 2407
2336 if (ptime->start > tprev) 2408 if (tprev && ptime->start > tprev)
2337 tprev = ptime->start; 2409 tprev = ptime->start;
2338 2410
2339 /* 2411 /*
@@ -2350,7 +2422,39 @@ static int timehist_sched_change_event(struct perf_tool *tool,
2350 t = ptime->end; 2422 t = ptime->end;
2351 } 2423 }
2352 2424
2353 timehist_update_runtime_stats(tr, t, tprev); 2425 if (!sched->idle_hist || thread->tid == 0) {
2426 timehist_update_runtime_stats(tr, t, tprev);
2427
2428 if (sched->idle_hist) {
2429 struct idle_thread_runtime *itr = (void *)tr;
2430 struct thread_runtime *last_tr;
2431
2432 BUG_ON(thread->tid != 0);
2433
2434 if (itr->last_thread == NULL)
2435 goto out;
2436
2437 /* add current idle time as last thread's runtime */
2438 last_tr = thread__get_runtime(itr->last_thread);
2439 if (last_tr == NULL)
2440 goto out;
2441
2442 timehist_update_runtime_stats(last_tr, t, tprev);
2443 /*
2444 * remove delta time of last thread as it's not updated
2445 * and otherwise it will show an invalid value next
2446 * time. we only care total run time and run stat.
2447 */
2448 last_tr->dt_run = 0;
2449 last_tr->dt_wait = 0;
2450 last_tr->dt_delay = 0;
2451
2452 if (itr->cursor.nr)
2453 callchain_append(&itr->callchain, &itr->cursor, t - tprev);
2454
2455 itr->last_thread = NULL;
2456 }
2457 }
2354 2458
2355 if (!sched->summary_only) 2459 if (!sched->summary_only)
2356 timehist_print_sample(sched, sample, &al, thread, t); 2460 timehist_print_sample(sched, sample, &al, thread, t);
@@ -2457,6 +2561,60 @@ static int show_deadthread_runtime(struct thread *t, void *priv)
2457 return __show_thread_runtime(t, priv); 2561 return __show_thread_runtime(t, priv);
2458} 2562}
2459 2563
2564static size_t callchain__fprintf_folded(FILE *fp, struct callchain_node *node)
2565{
2566 const char *sep = " <- ";
2567 struct callchain_list *chain;
2568 size_t ret = 0;
2569 char bf[1024];
2570 bool first;
2571
2572 if (node == NULL)
2573 return 0;
2574
2575 ret = callchain__fprintf_folded(fp, node->parent);
2576 first = (ret == 0);
2577
2578 list_for_each_entry(chain, &node->val, list) {
2579 if (chain->ip >= PERF_CONTEXT_MAX)
2580 continue;
2581 if (chain->ms.sym && chain->ms.sym->ignore)
2582 continue;
2583 ret += fprintf(fp, "%s%s", first ? "" : sep,
2584 callchain_list__sym_name(chain, bf, sizeof(bf),
2585 false));
2586 first = false;
2587 }
2588
2589 return ret;
2590}
2591
2592static size_t timehist_print_idlehist_callchain(struct rb_root *root)
2593{
2594 size_t ret = 0;
2595 FILE *fp = stdout;
2596 struct callchain_node *chain;
2597 struct rb_node *rb_node = rb_first(root);
2598
2599 printf(" %16s %8s %s\n", "Idle time (msec)", "Count", "Callchains");
2600 printf(" %.16s %.8s %.50s\n", graph_dotted_line, graph_dotted_line,
2601 graph_dotted_line);
2602
2603 while (rb_node) {
2604 chain = rb_entry(rb_node, struct callchain_node, rb_node);
2605 rb_node = rb_next(rb_node);
2606
2607 ret += fprintf(fp, " ");
2608 print_sched_time(chain->hit, 12);
2609 ret += 16; /* print_sched_time returns 2nd arg + 4 */
2610 ret += fprintf(fp, " %8d ", chain->count);
2611 ret += callchain__fprintf_folded(fp, chain);
2612 ret += fprintf(fp, "\n");
2613 }
2614
2615 return ret;
2616}
2617
2460static void timehist_print_summary(struct perf_sched *sched, 2618static void timehist_print_summary(struct perf_sched *sched,
2461 struct perf_session *session) 2619 struct perf_session *session)
2462{ 2620{
@@ -2469,12 +2627,15 @@ static void timehist_print_summary(struct perf_sched *sched,
2469 2627
2470 memset(&totals, 0, sizeof(totals)); 2628 memset(&totals, 0, sizeof(totals));
2471 2629
2472 if (comm_width < 30) 2630 if (sched->idle_hist) {
2473 comm_width = 30; 2631 printf("\nIdle-time summary\n");
2474 2632 printf("%*s parent sched-out ", comm_width, "comm");
2475 printf("\nRuntime summary\n"); 2633 printf(" idle-time min-idle avg-idle max-idle stddev migrations\n");
2476 printf("%*s parent sched-in ", comm_width, "comm"); 2634 } else {
2477 printf(" run-time min-run avg-run max-run stddev migrations\n"); 2635 printf("\nRuntime summary\n");
2636 printf("%*s parent sched-in ", comm_width, "comm");
2637 printf(" run-time min-run avg-run max-run stddev migrations\n");
2638 }
2478 printf("%*s (count) ", comm_width, ""); 2639 printf("%*s (count) ", comm_width, "");
2479 printf(" (msec) (msec) (msec) (msec) %%\n"); 2640 printf(" (msec) (msec) (msec) (msec) %%\n");
2480 printf("%.117s\n", graph_dotted_line); 2641 printf("%.117s\n", graph_dotted_line);
@@ -2490,7 +2651,7 @@ static void timehist_print_summary(struct perf_sched *sched,
2490 printf("<no terminated tasks>\n"); 2651 printf("<no terminated tasks>\n");
2491 2652
2492 /* CPU idle stats not tracked when samples were skipped */ 2653 /* CPU idle stats not tracked when samples were skipped */
2493 if (sched->skipped_samples) 2654 if (sched->skipped_samples && !sched->idle_hist)
2494 return; 2655 return;
2495 2656
2496 printf("\nIdle stats:\n"); 2657 printf("\nIdle stats:\n");
@@ -2509,6 +2670,35 @@ static void timehist_print_summary(struct perf_sched *sched,
2509 printf(" CPU %2d idle entire time window\n", i); 2670 printf(" CPU %2d idle entire time window\n", i);
2510 } 2671 }
2511 2672
2673 if (sched->idle_hist && symbol_conf.use_callchain) {
2674 callchain_param.mode = CHAIN_FOLDED;
2675 callchain_param.value = CCVAL_PERIOD;
2676
2677 callchain_register_param(&callchain_param);
2678
2679 printf("\nIdle stats by callchain:\n");
2680 for (i = 0; i < idle_max_cpu; ++i) {
2681 struct idle_thread_runtime *itr;
2682
2683 t = idle_threads[i];
2684 if (!t)
2685 continue;
2686
2687 itr = thread__priv(t);
2688 if (itr == NULL)
2689 continue;
2690
2691 callchain_param.sort(&itr->sorted_root, &itr->callchain,
2692 0, &callchain_param);
2693
2694 printf(" CPU %2d:", i);
2695 print_sched_time(itr->tr.total_run_time, 6);
2696 printf(" msec\n");
2697 timehist_print_idlehist_callchain(&itr->sorted_root);
2698 printf("\n");
2699 }
2700 }
2701
2512 printf("\n" 2702 printf("\n"
2513 " Total number of unique tasks: %" PRIu64 "\n" 2703 " Total number of unique tasks: %" PRIu64 "\n"
2514 "Total number of context switches: %" PRIu64 "\n" 2704 "Total number of context switches: %" PRIu64 "\n"
@@ -3036,6 +3226,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
3036 OPT_BOOLEAN('w', "wakeups", &sched.show_wakeups, "Show wakeup events"), 3226 OPT_BOOLEAN('w', "wakeups", &sched.show_wakeups, "Show wakeup events"),
3037 OPT_BOOLEAN('M', "migrations", &sched.show_migrations, "Show migration events"), 3227 OPT_BOOLEAN('M', "migrations", &sched.show_migrations, "Show migration events"),
3038 OPT_BOOLEAN('V', "cpu-visual", &sched.show_cpu_visual, "Add CPU visual"), 3228 OPT_BOOLEAN('V', "cpu-visual", &sched.show_cpu_visual, "Add CPU visual"),
3229 OPT_BOOLEAN('I', "idle-hist", &sched.idle_hist, "Show idle events only"),
3039 OPT_STRING(0, "time", &sched.time_str, "str", 3230 OPT_STRING(0, "time", &sched.time_str, "str",
3040 "Time span for analysis (start,stop)"), 3231 "Time span for analysis (start,stop)"),
3041 OPT_PARENT(sched_options) 3232 OPT_PARENT(sched_options)
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 688dea7cb08f..a02f2e965628 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -2195,7 +2195,7 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
2195} 2195}
2196 2196
2197static 2197static
2198int process_stat_config_event(struct perf_tool *tool __maybe_unused, 2198int process_stat_config_event(struct perf_tool *tool,
2199 union perf_event *event, 2199 union perf_event *event,
2200 struct perf_session *session __maybe_unused) 2200 struct perf_session *session __maybe_unused)
2201{ 2201{
@@ -2238,7 +2238,7 @@ static int set_maps(struct perf_stat *st)
2238} 2238}
2239 2239
2240static 2240static
2241int process_thread_map_event(struct perf_tool *tool __maybe_unused, 2241int process_thread_map_event(struct perf_tool *tool,
2242 union perf_event *event, 2242 union perf_event *event,
2243 struct perf_session *session __maybe_unused) 2243 struct perf_session *session __maybe_unused)
2244{ 2244{
@@ -2257,7 +2257,7 @@ int process_thread_map_event(struct perf_tool *tool __maybe_unused,
2257} 2257}
2258 2258
2259static 2259static
2260int process_cpu_map_event(struct perf_tool *tool __maybe_unused, 2260int process_cpu_map_event(struct perf_tool *tool,
2261 union perf_event *event, 2261 union perf_event *event,
2262 struct perf_session *session __maybe_unused) 2262 struct perf_session *session __maybe_unused)
2263{ 2263{
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
new file mode 100755
index 000000000000..c747bfd7f14d
--- /dev/null
+++ b/tools/perf/check-headers.sh
@@ -0,0 +1,59 @@
1#!/bin/sh
2
3HEADERS='
4include/uapi/linux/perf_event.h
5include/linux/hash.h
6include/uapi/linux/hw_breakpoint.h
7arch/x86/include/asm/disabled-features.h
8arch/x86/include/asm/required-features.h
9arch/x86/include/asm/cpufeatures.h
10arch/arm/include/uapi/asm/perf_regs.h
11arch/arm64/include/uapi/asm/perf_regs.h
12arch/powerpc/include/uapi/asm/perf_regs.h
13arch/x86/include/uapi/asm/perf_regs.h
14arch/x86/include/uapi/asm/kvm.h
15arch/x86/include/uapi/asm/kvm_perf.h
16arch/x86/include/uapi/asm/svm.h
17arch/x86/include/uapi/asm/vmx.h
18arch/powerpc/include/uapi/asm/kvm.h
19arch/s390/include/uapi/asm/kvm.h
20arch/s390/include/uapi/asm/kvm_perf.h
21arch/s390/include/uapi/asm/sie.h
22arch/arm/include/uapi/asm/kvm.h
23arch/arm64/include/uapi/asm/kvm.h
24include/asm-generic/bitops/arch_hweight.h
25include/asm-generic/bitops/const_hweight.h
26include/asm-generic/bitops/__fls.h
27include/asm-generic/bitops/fls.h
28include/asm-generic/bitops/fls64.h
29include/linux/coresight-pmu.h
30include/uapi/asm-generic/mman-common.h
31'
32
33check () {
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
51for i in $HEADERS; do
52 check $i -B
53done
54
55# diff with extra ignore lines
56check arch/x86/lib/memcpy_64.S -B -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"
57check arch/x86/lib/memset_64.S -B -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"
58check include/uapi/asm-generic/mman.h -B -I "^#include <\(uapi/\)*asm-generic/mman-common.h>"
59check include/uapi/linux/mman.h -B -I "^#include <\(uapi/\)*asm/mman.h>"
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 9a0236a4cf95..1c27d947c2fe 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -55,6 +55,7 @@ struct record_opts {
55 bool all_user; 55 bool all_user;
56 bool tail_synthesize; 56 bool tail_synthesize;
57 bool overwrite; 57 bool overwrite;
58 bool ignore_missing_thread;
58 unsigned int freq; 59 unsigned int freq;
59 unsigned int mmap_pages; 60 unsigned int mmap_pages;
60 unsigned int auxtrace_mmap_pages; 61 unsigned int auxtrace_mmap_pages;
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 23605202d4a1..a77dcc0d24e3 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -186,6 +186,10 @@ static struct test generic_tests[] = {
186 .func = test__thread_map_synthesize, 186 .func = test__thread_map_synthesize,
187 }, 187 },
188 { 188 {
189 .desc = "Remove thread map",
190 .func = test__thread_map_remove,
191 },
192 {
189 .desc = "Synthesize cpu map", 193 .desc = "Synthesize cpu map",
190 .func = test__cpu_map_synthesize, 194 .func = test__cpu_map_synthesize,
191 }, 195 },
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 0d7b251305af..a512f0c8ff5b 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -80,6 +80,7 @@ const char *test__bpf_subtest_get_desc(int subtest);
80int test__bpf_subtest_get_nr(void); 80int test__bpf_subtest_get_nr(void);
81int test_session_topology(int subtest); 81int test_session_topology(int subtest);
82int test__thread_map_synthesize(int subtest); 82int test__thread_map_synthesize(int subtest);
83int test__thread_map_remove(int subtest);
83int test__cpu_map_synthesize(int subtest); 84int test__cpu_map_synthesize(int subtest);
84int test__synthesize_stat_config(int subtest); 85int test__synthesize_stat_config(int subtest);
85int test__synthesize_stat(int subtest); 86int test__synthesize_stat(int subtest);
diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
index cee2a2cdc933..a4a4b4625ac3 100644
--- a/tools/perf/tests/thread-map.c
+++ b/tools/perf/tests/thread-map.c
@@ -1,3 +1,4 @@
1#include <stdlib.h>
1#include <sys/types.h> 2#include <sys/types.h>
2#include <unistd.h> 3#include <unistd.h>
3#include <sys/prctl.h> 4#include <sys/prctl.h>
@@ -93,3 +94,46 @@ int test__thread_map_synthesize(int subtest __maybe_unused)
93 94
94 return 0; 95 return 0;
95} 96}
97
98int test__thread_map_remove(int subtest __maybe_unused)
99{
100 struct thread_map *threads;
101 char *str;
102 int i;
103
104 TEST_ASSERT_VAL("failed to allocate map string",
105 asprintf(&str, "%d,%d", getpid(), getppid()) >= 0);
106
107 threads = thread_map__new_str(str, NULL, 0);
108
109 TEST_ASSERT_VAL("failed to allocate thread_map",
110 threads);
111
112 if (verbose)
113 thread_map__fprintf(threads, stderr);
114
115 TEST_ASSERT_VAL("failed to remove thread",
116 !thread_map__remove(threads, 0));
117
118 TEST_ASSERT_VAL("thread_map count != 1", threads->nr == 1);
119
120 if (verbose)
121 thread_map__fprintf(threads, stderr);
122
123 TEST_ASSERT_VAL("failed to remove thread",
124 !thread_map__remove(threads, 0));
125
126 TEST_ASSERT_VAL("thread_map count != 0", threads->nr == 0);
127
128 if (verbose)
129 thread_map__fprintf(threads, stderr);
130
131 TEST_ASSERT_VAL("failed to not remove thread",
132 thread_map__remove(threads, 0));
133
134 for (i = 0; i < threads->nr; i++)
135 free(threads->map[i].comm);
136
137 free(threads);
138 return 0;
139}
diff --git a/tools/perf/trace/beauty/mmap.c b/tools/perf/trace/beauty/mmap.c
index fd710ab33684..af1cfde6b97b 100644
--- a/tools/perf/trace/beauty/mmap.c
+++ b/tools/perf/trace/beauty/mmap.c
@@ -42,7 +42,9 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
42 42
43 P_MMAP_FLAG(SHARED); 43 P_MMAP_FLAG(SHARED);
44 P_MMAP_FLAG(PRIVATE); 44 P_MMAP_FLAG(PRIVATE);
45#ifdef MAP_32BIT
45 P_MMAP_FLAG(32BIT); 46 P_MMAP_FLAG(32BIT);
47#endif
46 P_MMAP_FLAG(ANONYMOUS); 48 P_MMAP_FLAG(ANONYMOUS);
47 P_MMAP_FLAG(DENYWRITE); 49 P_MMAP_FLAG(DENYWRITE);
48 P_MMAP_FLAG(EXECUTABLE); 50 P_MMAP_FLAG(EXECUTABLE);
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index ec7a30fad149..ba36aac340bc 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -215,7 +215,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
215 ui_browser__set_color(browser, color); 215 ui_browser__set_color(browser, color);
216 if (dl->ins.ops && dl->ins.ops->scnprintf) { 216 if (dl->ins.ops && dl->ins.ops->scnprintf) {
217 if (ins__is_jump(&dl->ins)) { 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 ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR : 220 ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR :
221 SLSMG_UARROW_CHAR); 221 SLSMG_UARROW_CHAR);
@@ -245,7 +245,8 @@ static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sy
245{ 245{
246 if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins) 246 if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins)
247 || !disasm_line__has_offset(dl) 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 return false; 250 return false;
250 251
251 return true; 252 return true;
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index ea7e0de4b9c1..06cc04e5806a 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -223,13 +223,19 @@ bool ins__is_call(const struct ins *ins)
223static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map *map __maybe_unused) 223static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map *map __maybe_unused)
224{ 224{
225 const char *s = strchr(ops->raw, '+'); 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 if (c++ != NULL)
229 ops->target.addr = strtoull(c, NULL, 16);
230 else
231 ops->target.addr = strtoull(ops->raw, NULL, 16);
228 232
229 if (s++ != NULL) 233 if (s++ != NULL) {
230 ops->target.offset = strtoull(s, NULL, 16); 234 ops->target.offset = strtoull(s, NULL, 16);
231 else 235 ops->target.offset_avail = true;
232 ops->target.offset = UINT64_MAX; 236 } else {
237 ops->target.offset_avail = false;
238 }
233 239
234 return 0; 240 return 0;
235} 241}
@@ -237,7 +243,7 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
237static int jump__scnprintf(struct ins *ins, char *bf, size_t size, 243static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
238 struct ins_operands *ops) 244 struct ins_operands *ops)
239{ 245{
240 if (!ops->target.addr) 246 if (!ops->target.addr || ops->target.offset < 0)
241 return ins__raw_scnprintf(ins, bf, size, ops); 247 return ins__raw_scnprintf(ins, bf, size, ops);
242 248
243 return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset); 249 return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset);
@@ -641,7 +647,8 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
641 647
642 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); 648 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
643 649
644 if (addr < sym->start || addr >= sym->end) { 650 if ((addr < sym->start || addr >= sym->end) &&
651 (addr != sym->end || sym->start != sym->end)) {
645 pr_debug("%s(%d): ERANGE! sym->name=%s, start=%#" PRIx64 ", addr=%#" PRIx64 ", end=%#" PRIx64 "\n", 652 pr_debug("%s(%d): ERANGE! sym->name=%s, start=%#" PRIx64 ", addr=%#" PRIx64 ", end=%#" PRIx64 "\n",
646 __func__, __LINE__, sym->name, sym->start, addr, sym->end); 653 __func__, __LINE__, sym->name, sym->start, addr, sym->end);
647 return -ERANGE; 654 return -ERANGE;
@@ -1205,9 +1212,11 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
1205 if (dl == NULL) 1212 if (dl == NULL)
1206 return -1; 1213 return -1;
1207 1214
1208 if (dl->ops.target.offset == UINT64_MAX) 1215 if (!disasm_line__has_offset(dl)) {
1209 dl->ops.target.offset = dl->ops.target.addr - 1216 dl->ops.target.offset = dl->ops.target.addr -
1210 map__rip_2objdump(map, sym->start); 1217 map__rip_2objdump(map, sym->start);
1218 dl->ops.target.offset_avail = true;
1219 }
1211 1220
1212 /* kcore has no symbols, so add the call target name */ 1221 /* kcore has no symbols, so add the call target name */
1213 if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.name) { 1222 if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.name) {
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 87e4cadc5d27..09776b5af991 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -24,7 +24,8 @@ struct ins_operands {
24 char *raw; 24 char *raw;
25 char *name; 25 char *name;
26 u64 addr; 26 u64 addr;
27 u64 offset; 27 s64 offset;
28 bool offset_avail;
28 } target; 29 } target;
29 union { 30 union {
30 struct { 31 struct {
@@ -68,7 +69,7 @@ struct disasm_line {
68 69
69static inline bool disasm_line__has_offset(const struct disasm_line *dl) 70static inline bool disasm_line__has_offset(const struct disasm_line *dl)
70{ 71{
71 return dl->ops.target.offset != UINT64_MAX; 72 return dl->ops.target.offset_avail;
72} 73}
73 74
74void disasm_line__free(struct disasm_line *dl); 75void disasm_line__free(struct disasm_line *dl);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index b2365a63db45..04e536ae4d88 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -990,6 +990,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
990 * it overloads any global configuration. 990 * it overloads any global configuration.
991 */ 991 */
992 apply_config_terms(evsel, opts); 992 apply_config_terms(evsel, opts);
993
994 evsel->ignore_missing_thread = opts->ignore_missing_thread;
993} 995}
994 996
995static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 997static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
@@ -1419,6 +1421,33 @@ static int __open_attr__fprintf(FILE *fp, const char *name, const char *val,
1419 return fprintf(fp, " %-32s %s\n", name, val); 1421 return fprintf(fp, " %-32s %s\n", name, val);
1420} 1422}
1421 1423
1424static bool ignore_missing_thread(struct perf_evsel *evsel,
1425 struct thread_map *threads,
1426 int thread, int err)
1427{
1428 if (!evsel->ignore_missing_thread)
1429 return false;
1430
1431 /* The system wide setup does not work with threads. */
1432 if (evsel->system_wide)
1433 return false;
1434
1435 /* The -ESRCH is perf event syscall errno for pid's not found. */
1436 if (err != -ESRCH)
1437 return false;
1438
1439 /* If there's only one thread, let it fail. */
1440 if (threads->nr == 1)
1441 return false;
1442
1443 if (thread_map__remove(threads, thread))
1444 return false;
1445
1446 pr_warning("WARNING: Ignored open failure for pid %d\n",
1447 thread_map__pid(threads, thread));
1448 return true;
1449}
1450
1422static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 1451static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
1423 struct thread_map *threads) 1452 struct thread_map *threads)
1424{ 1453{
@@ -1474,7 +1503,7 @@ retry_sample_id:
1474 for (cpu = 0; cpu < cpus->nr; cpu++) { 1503 for (cpu = 0; cpu < cpus->nr; cpu++) {
1475 1504
1476 for (thread = 0; thread < nthreads; thread++) { 1505 for (thread = 0; thread < nthreads; thread++) {
1477 int group_fd; 1506 int fd, group_fd;
1478 1507
1479 if (!evsel->cgrp && !evsel->system_wide) 1508 if (!evsel->cgrp && !evsel->system_wide)
1480 pid = thread_map__pid(threads, thread); 1509 pid = thread_map__pid(threads, thread);
@@ -1484,21 +1513,37 @@ retry_open:
1484 pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx", 1513 pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx",
1485 pid, cpus->map[cpu], group_fd, flags); 1514 pid, cpus->map[cpu], group_fd, flags);
1486 1515
1487 FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr, 1516 fd = sys_perf_event_open(&evsel->attr, pid, cpus->map[cpu],
1488 pid, 1517 group_fd, flags);
1489 cpus->map[cpu], 1518
1490 group_fd, flags); 1519 FD(evsel, cpu, thread) = fd;
1491 if (FD(evsel, cpu, thread) < 0) { 1520
1521 if (fd < 0) {
1492 err = -errno; 1522 err = -errno;
1523
1524 if (ignore_missing_thread(evsel, threads, thread, err)) {
1525 /*
1526 * We just removed 1 thread, so take a step
1527 * back on thread index and lower the upper
1528 * nthreads limit.
1529 */
1530 nthreads--;
1531 thread--;
1532
1533 /* ... and pretend like nothing have happened. */
1534 err = 0;
1535 continue;
1536 }
1537
1493 pr_debug2("\nsys_perf_event_open failed, error %d\n", 1538 pr_debug2("\nsys_perf_event_open failed, error %d\n",
1494 err); 1539 err);
1495 goto try_fallback; 1540 goto try_fallback;
1496 } 1541 }
1497 1542
1498 pr_debug2(" = %d\n", FD(evsel, cpu, thread)); 1543 pr_debug2(" = %d\n", fd);
1499 1544
1500 if (evsel->bpf_fd >= 0) { 1545 if (evsel->bpf_fd >= 0) {
1501 int evt_fd = FD(evsel, cpu, thread); 1546 int evt_fd = fd;
1502 int bpf_fd = evsel->bpf_fd; 1547 int bpf_fd = evsel->bpf_fd;
1503 1548
1504 err = ioctl(evt_fd, 1549 err = ioctl(evt_fd,
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 6abb89cd27f9..06ef6f29efa1 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -120,6 +120,7 @@ struct perf_evsel {
120 bool tracking; 120 bool tracking;
121 bool per_pkg; 121 bool per_pkg;
122 bool precise_max; 122 bool precise_max;
123 bool ignore_missing_thread;
123 /* parse modifier helper */ 124 /* parse modifier helper */
124 int exclude_GH; 125 int exclude_GH;
125 int nr_members; 126 int nr_members;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index df2482b2ba45..dc93940de351 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1459,7 +1459,8 @@ int dso__load(struct dso *dso, struct map *map)
1459 * Read the build id if possible. This is required for 1459 * Read the build id if possible. This is required for
1460 * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work 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 filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0) 1464 filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0)
1464 dso__set_build_id(dso, build_id); 1465 dso__set_build_id(dso, build_id);
1465 1466
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 40585f5b7027..f9eab200fd75 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -448,3 +448,25 @@ bool thread_map__has(struct thread_map *threads, pid_t pid)
448 448
449 return false; 449 return false;
450} 450}
451
452int 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}
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index bd3b971588da..ea0ef08c6303 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -58,4 +58,5 @@ static inline char *thread_map__comm(struct thread_map *map, int thread)
58 58
59void thread_map__read_comms(struct thread_map *threads); 59void thread_map__read_comms(struct thread_map *threads);
60bool thread_map__has(struct thread_map *threads, pid_t pid); 60bool thread_map__has(struct thread_map *threads, pid_t pid);
61int thread_map__remove(struct thread_map *threads, int idx);
61#endif /* __PERF_THREAD_MAP_H */ 62#endif /* __PERF_THREAD_MAP_H */