aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/build/Makefile.feature4
-rw-r--r--tools/build/feature/Makefile10
-rw-r--r--tools/gpio/Makefile2
-rw-r--r--tools/include/uapi/linux/usbdevice_fs.h201
-rw-r--r--tools/perf/Makefile.config44
-rw-r--r--tools/perf/Makefile.perf8
-rw-r--r--tools/perf/builtin-c2c.c4
-rw-r--r--tools/perf/builtin-script.c21
-rw-r--r--tools/perf/builtin-trace.c142
-rwxr-xr-xtools/perf/check-headers.sh1
-rw-r--r--tools/perf/trace/beauty/beauty.h7
-rw-r--r--tools/perf/trace/beauty/ioctl.c22
-rw-r--r--tools/perf/trace/beauty/mmap.c2
-rw-r--r--tools/perf/trace/beauty/seccomp.c4
-rwxr-xr-xtools/perf/trace/beauty/usbdevfs_ioctl.sh19
-rw-r--r--tools/perf/util/dump-insn.c8
-rw-r--r--tools/perf/util/dump-insn.h2
-rw-r--r--tools/perf/util/intel-bts.c4
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c8
-rw-r--r--tools/perf/util/intel-pt.c6
-rw-r--r--tools/perf/util/python.c3
-rw-r--r--tools/perf/util/session.c7
-rw-r--r--tools/perf/util/thread-stack.c227
-rw-r--r--tools/perf/util/thread-stack.h8
-rw-r--r--tools/power/x86/turbostat/Makefile8
-rw-r--r--tools/power/x86/x86_energy_perf_policy/Makefile6
-rw-r--r--tools/thermal/tmon/Makefile8
27 files changed, 620 insertions, 166 deletions
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index d47b8f73e2e7..5467c6bf9ceb 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -82,8 +82,8 @@ FEATURE_TESTS_EXTRA := \
82 cplus-demangle \ 82 cplus-demangle \
83 hello \ 83 hello \
84 libbabeltrace \ 84 libbabeltrace \
85 liberty \ 85 libbfd-liberty \
86 liberty-z \ 86 libbfd-liberty-z \
87 libunwind-debug-frame \ 87 libunwind-debug-frame \
88 libunwind-debug-frame-arm \ 88 libunwind-debug-frame-arm \
89 libunwind-debug-frame-aarch64 \ 89 libunwind-debug-frame-aarch64 \
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index 2dbcc0d00f52..7ceb4441b627 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -17,8 +17,8 @@ FILES= \
17 test-libbfd.bin \ 17 test-libbfd.bin \
18 test-disassembler-four-args.bin \ 18 test-disassembler-four-args.bin \
19 test-reallocarray.bin \ 19 test-reallocarray.bin \
20 test-liberty.bin \ 20 test-libbfd-liberty.bin \
21 test-liberty-z.bin \ 21 test-libbfd-liberty-z.bin \
22 test-cplus-demangle.bin \ 22 test-cplus-demangle.bin \
23 test-libelf.bin \ 23 test-libelf.bin \
24 test-libelf-getphdrnum.bin \ 24 test-libelf-getphdrnum.bin \
@@ -210,7 +210,7 @@ $(OUTPUT)test-libpython-version.bin:
210 $(BUILD) 210 $(BUILD)
211 211
212$(OUTPUT)test-libbfd.bin: 212$(OUTPUT)test-libbfd.bin:
213 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl 213 $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl
214 214
215$(OUTPUT)test-disassembler-four-args.bin: 215$(OUTPUT)test-disassembler-four-args.bin:
216 $(BUILD) -DPACKAGE='"perf"' -lbfd -lopcodes 216 $(BUILD) -DPACKAGE='"perf"' -lbfd -lopcodes
@@ -218,10 +218,10 @@ $(OUTPUT)test-disassembler-four-args.bin:
218$(OUTPUT)test-reallocarray.bin: 218$(OUTPUT)test-reallocarray.bin:
219 $(BUILD) 219 $(BUILD)
220 220
221$(OUTPUT)test-liberty.bin: 221$(OUTPUT)test-libbfd-liberty.bin:
222 $(CC) $(CFLAGS) -Wall -Werror -o $@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty 222 $(CC) $(CFLAGS) -Wall -Werror -o $@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty
223 223
224$(OUTPUT)test-liberty-z.bin: 224$(OUTPUT)test-libbfd-liberty-z.bin:
225 $(CC) $(CFLAGS) -Wall -Werror -o $@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty -lz 225 $(CC) $(CFLAGS) -Wall -Werror -o $@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty -lz
226 226
227$(OUTPUT)test-cplus-demangle.bin: 227$(OUTPUT)test-cplus-demangle.bin:
diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile
index 240eda014b37..6ecdd1067826 100644
--- a/tools/gpio/Makefile
+++ b/tools/gpio/Makefile
@@ -12,7 +12,7 @@ endif
12# (this improves performance and avoids hard-to-debug behaviour); 12# (this improves performance and avoids hard-to-debug behaviour);
13MAKEFLAGS += -r 13MAKEFLAGS += -r
14 14
15CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include 15override CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
16 16
17ALL_TARGETS := lsgpio gpio-hammer gpio-event-mon 17ALL_TARGETS := lsgpio gpio-hammer gpio-event-mon
18ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS)) 18ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS))
diff --git a/tools/include/uapi/linux/usbdevice_fs.h b/tools/include/uapi/linux/usbdevice_fs.h
new file mode 100644
index 000000000000..964e87217be4
--- /dev/null
+++ b/tools/include/uapi/linux/usbdevice_fs.h
@@ -0,0 +1,201 @@
1/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
2/*****************************************************************************/
3
4/*
5 * usbdevice_fs.h -- USB device file system.
6 *
7 * Copyright (C) 2000
8 * Thomas Sailer (sailer@ife.ee.ethz.ch)
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 * History:
25 * 0.1 04.01.2000 Created
26 */
27
28/*****************************************************************************/
29
30#ifndef _UAPI_LINUX_USBDEVICE_FS_H
31#define _UAPI_LINUX_USBDEVICE_FS_H
32
33#include <linux/types.h>
34#include <linux/magic.h>
35
36/* --------------------------------------------------------------------- */
37
38/* usbdevfs ioctl codes */
39
40struct usbdevfs_ctrltransfer {
41 __u8 bRequestType;
42 __u8 bRequest;
43 __u16 wValue;
44 __u16 wIndex;
45 __u16 wLength;
46 __u32 timeout; /* in milliseconds */
47 void __user *data;
48};
49
50struct usbdevfs_bulktransfer {
51 unsigned int ep;
52 unsigned int len;
53 unsigned int timeout; /* in milliseconds */
54 void __user *data;
55};
56
57struct usbdevfs_setinterface {
58 unsigned int interface;
59 unsigned int altsetting;
60};
61
62struct usbdevfs_disconnectsignal {
63 unsigned int signr;
64 void __user *context;
65};
66
67#define USBDEVFS_MAXDRIVERNAME 255
68
69struct usbdevfs_getdriver {
70 unsigned int interface;
71 char driver[USBDEVFS_MAXDRIVERNAME + 1];
72};
73
74struct usbdevfs_connectinfo {
75 unsigned int devnum;
76 unsigned char slow;
77};
78
79#define USBDEVFS_URB_SHORT_NOT_OK 0x01
80#define USBDEVFS_URB_ISO_ASAP 0x02
81#define USBDEVFS_URB_BULK_CONTINUATION 0x04
82#define USBDEVFS_URB_NO_FSBR 0x20 /* Not used */
83#define USBDEVFS_URB_ZERO_PACKET 0x40
84#define USBDEVFS_URB_NO_INTERRUPT 0x80
85
86#define USBDEVFS_URB_TYPE_ISO 0
87#define USBDEVFS_URB_TYPE_INTERRUPT 1
88#define USBDEVFS_URB_TYPE_CONTROL 2
89#define USBDEVFS_URB_TYPE_BULK 3
90
91struct usbdevfs_iso_packet_desc {
92 unsigned int length;
93 unsigned int actual_length;
94 unsigned int status;
95};
96
97struct usbdevfs_urb {
98 unsigned char type;
99 unsigned char endpoint;
100 int status;
101 unsigned int flags;
102 void __user *buffer;
103 int buffer_length;
104 int actual_length;
105 int start_frame;
106 union {
107 int number_of_packets; /* Only used for isoc urbs */
108 unsigned int stream_id; /* Only used with bulk streams */
109 };
110 int error_count;
111 unsigned int signr; /* signal to be sent on completion,
112 or 0 if none should be sent. */
113 void __user *usercontext;
114 struct usbdevfs_iso_packet_desc iso_frame_desc[0];
115};
116
117/* ioctls for talking directly to drivers */
118struct usbdevfs_ioctl {
119 int ifno; /* interface 0..N ; negative numbers reserved */
120 int ioctl_code; /* MUST encode size + direction of data so the
121 * macros in <asm/ioctl.h> give correct values */
122 void __user *data; /* param buffer (in, or out) */
123};
124
125/* You can do most things with hubs just through control messages,
126 * except find out what device connects to what port. */
127struct usbdevfs_hub_portinfo {
128 char nports; /* number of downstream ports in this hub */
129 char port [127]; /* e.g. port 3 connects to device 27 */
130};
131
132/* System and bus capability flags */
133#define USBDEVFS_CAP_ZERO_PACKET 0x01
134#define USBDEVFS_CAP_BULK_CONTINUATION 0x02
135#define USBDEVFS_CAP_NO_PACKET_SIZE_LIM 0x04
136#define USBDEVFS_CAP_BULK_SCATTER_GATHER 0x08
137#define USBDEVFS_CAP_REAP_AFTER_DISCONNECT 0x10
138#define USBDEVFS_CAP_MMAP 0x20
139#define USBDEVFS_CAP_DROP_PRIVILEGES 0x40
140
141/* USBDEVFS_DISCONNECT_CLAIM flags & struct */
142
143/* disconnect-and-claim if the driver matches the driver field */
144#define USBDEVFS_DISCONNECT_CLAIM_IF_DRIVER 0x01
145/* disconnect-and-claim except when the driver matches the driver field */
146#define USBDEVFS_DISCONNECT_CLAIM_EXCEPT_DRIVER 0x02
147
148struct usbdevfs_disconnect_claim {
149 unsigned int interface;
150 unsigned int flags;
151 char driver[USBDEVFS_MAXDRIVERNAME + 1];
152};
153
154struct usbdevfs_streams {
155 unsigned int num_streams; /* Not used by USBDEVFS_FREE_STREAMS */
156 unsigned int num_eps;
157 unsigned char eps[0];
158};
159
160/*
161 * USB_SPEED_* values returned by USBDEVFS_GET_SPEED are defined in
162 * linux/usb/ch9.h
163 */
164
165#define USBDEVFS_CONTROL _IOWR('U', 0, struct usbdevfs_ctrltransfer)
166#define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32)
167#define USBDEVFS_BULK _IOWR('U', 2, struct usbdevfs_bulktransfer)
168#define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32)
169#define USBDEVFS_RESETEP _IOR('U', 3, unsigned int)
170#define USBDEVFS_SETINTERFACE _IOR('U', 4, struct usbdevfs_setinterface)
171#define USBDEVFS_SETCONFIGURATION _IOR('U', 5, unsigned int)
172#define USBDEVFS_GETDRIVER _IOW('U', 8, struct usbdevfs_getdriver)
173#define USBDEVFS_SUBMITURB _IOR('U', 10, struct usbdevfs_urb)
174#define USBDEVFS_SUBMITURB32 _IOR('U', 10, struct usbdevfs_urb32)
175#define USBDEVFS_DISCARDURB _IO('U', 11)
176#define USBDEVFS_REAPURB _IOW('U', 12, void *)
177#define USBDEVFS_REAPURB32 _IOW('U', 12, __u32)
178#define USBDEVFS_REAPURBNDELAY _IOW('U', 13, void *)
179#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, __u32)
180#define USBDEVFS_DISCSIGNAL _IOR('U', 14, struct usbdevfs_disconnectsignal)
181#define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32)
182#define USBDEVFS_CLAIMINTERFACE _IOR('U', 15, unsigned int)
183#define USBDEVFS_RELEASEINTERFACE _IOR('U', 16, unsigned int)
184#define USBDEVFS_CONNECTINFO _IOW('U', 17, struct usbdevfs_connectinfo)
185#define USBDEVFS_IOCTL _IOWR('U', 18, struct usbdevfs_ioctl)
186#define USBDEVFS_IOCTL32 _IOWR('U', 18, struct usbdevfs_ioctl32)
187#define USBDEVFS_HUB_PORTINFO _IOR('U', 19, struct usbdevfs_hub_portinfo)
188#define USBDEVFS_RESET _IO('U', 20)
189#define USBDEVFS_CLEAR_HALT _IOR('U', 21, unsigned int)
190#define USBDEVFS_DISCONNECT _IO('U', 22)
191#define USBDEVFS_CONNECT _IO('U', 23)
192#define USBDEVFS_CLAIM_PORT _IOR('U', 24, unsigned int)
193#define USBDEVFS_RELEASE_PORT _IOR('U', 25, unsigned int)
194#define USBDEVFS_GET_CAPABILITIES _IOR('U', 26, __u32)
195#define USBDEVFS_DISCONNECT_CLAIM _IOR('U', 27, struct usbdevfs_disconnect_claim)
196#define USBDEVFS_ALLOC_STREAMS _IOR('U', 28, struct usbdevfs_streams)
197#define USBDEVFS_FREE_STREAMS _IOR('U', 29, struct usbdevfs_streams)
198#define USBDEVFS_DROP_PRIVILEGES _IOW('U', 30, __u32)
199#define USBDEVFS_GET_SPEED _IO('U', 31)
200
201#endif /* _UAPI_LINUX_USBDEVICE_FS_H */
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 07c1857c3d7a..b441c88cafa1 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -702,18 +702,20 @@ endif
702 702
703ifeq ($(feature-libbfd), 1) 703ifeq ($(feature-libbfd), 1)
704 EXTLIBS += -lbfd 704 EXTLIBS += -lbfd
705else
706 # we are on a system that requires -liberty and (maybe) -lz
707 # to link against -lbfd; test each case individually here
705 708
706 # call all detections now so we get correct 709 # call all detections now so we get correct
707 # status in VF output 710 # status in VF output
708 $(call feature_check,liberty) 711 $(call feature_check,libbfd-liberty)
709 $(call feature_check,liberty-z) 712 $(call feature_check,libbfd-liberty-z)
710 $(call feature_check,cplus-demangle)
711 713
712 ifeq ($(feature-liberty), 1) 714 ifeq ($(feature-libbfd-liberty), 1)
713 EXTLIBS += -liberty 715 EXTLIBS += -lbfd -liberty
714 else 716 else
715 ifeq ($(feature-liberty-z), 1) 717 ifeq ($(feature-libbfd-liberty-z), 1)
716 EXTLIBS += -liberty -lz 718 EXTLIBS += -lbfd -liberty -lz
717 endif 719 endif
718 endif 720 endif
719endif 721endif
@@ -723,24 +725,24 @@ ifdef NO_DEMANGLE
723else 725else
724 ifdef HAVE_CPLUS_DEMANGLE_SUPPORT 726 ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
725 EXTLIBS += -liberty 727 EXTLIBS += -liberty
726 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
727 else 728 else
728 ifneq ($(feature-libbfd), 1) 729 ifeq ($(filter -liberty,$(EXTLIBS)),)
729 ifneq ($(feature-liberty), 1) 730 $(call feature_check,cplus-demangle)
730 ifneq ($(feature-liberty-z), 1) 731
731 # we dont have neither HAVE_CPLUS_DEMANGLE_SUPPORT 732 # we dont have neither HAVE_CPLUS_DEMANGLE_SUPPORT
732 # or any of 'bfd iberty z' trinity 733 # or any of 'bfd iberty z' trinity
733 ifeq ($(feature-cplus-demangle), 1) 734 ifeq ($(feature-cplus-demangle), 1)
734 EXTLIBS += -liberty 735 EXTLIBS += -liberty
735 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT 736 else
736 else 737 msg := $(warning No bfd.h/libbfd found, please install binutils-dev[el]/zlib-static/libiberty-dev to gain symbol demangling)
737 msg := $(warning No bfd.h/libbfd found, please install binutils-dev[el]/zlib-static/libiberty-dev to gain symbol demangling) 738 CFLAGS += -DNO_DEMANGLE
738 CFLAGS += -DNO_DEMANGLE
739 endif
740 endif
741 endif 739 endif
742 endif 740 endif
743 endif 741 endif
742
743 ifneq ($(filter -liberty,$(EXTLIBS)),)
744 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
745 endif
744endif 746endif
745 747
746ifneq ($(filter -lbfd,$(EXTLIBS)),) 748ifneq ($(filter -lbfd,$(EXTLIBS)),)
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index bd23e3f30895..ff29c3372ec3 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -497,6 +497,12 @@ prctl_option_tbl := $(srctree)/tools/perf/trace/beauty/prctl_option.sh
497$(prctl_option_array): $(prctl_hdr_dir)/prctl.h $(prctl_option_tbl) 497$(prctl_option_array): $(prctl_hdr_dir)/prctl.h $(prctl_option_tbl)
498 $(Q)$(SHELL) '$(prctl_option_tbl)' $(prctl_hdr_dir) > $@ 498 $(Q)$(SHELL) '$(prctl_option_tbl)' $(prctl_hdr_dir) > $@
499 499
500usbdevfs_ioctl_array := $(beauty_ioctl_outdir)/usbdevfs_ioctl_array.c
501usbdevfs_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/usbdevfs_ioctl.sh
502
503$(usbdevfs_ioctl_array): $(linux_uapi_dir)/usbdevice_fs.h $(usbdevfs_ioctl_tbl)
504 $(Q)$(SHELL) '$(usbdevfs_ioctl_tbl)' $(linux_uapi_dir) > $@
505
500x86_arch_prctl_code_array := $(beauty_outdir)/x86_arch_prctl_code_array.c 506x86_arch_prctl_code_array := $(beauty_outdir)/x86_arch_prctl_code_array.c
501x86_arch_prctl_code_tbl := $(srctree)/tools/perf/trace/beauty/x86_arch_prctl.sh 507x86_arch_prctl_code_tbl := $(srctree)/tools/perf/trace/beauty/x86_arch_prctl.sh
502 508
@@ -624,6 +630,7 @@ prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders $(drm_ioc
624 $(mount_flags_array) \ 630 $(mount_flags_array) \
625 $(perf_ioctl_array) \ 631 $(perf_ioctl_array) \
626 $(prctl_option_array) \ 632 $(prctl_option_array) \
633 $(usbdevfs_ioctl_array) \
627 $(x86_arch_prctl_code_array) \ 634 $(x86_arch_prctl_code_array) \
628 $(rename_flags_array) \ 635 $(rename_flags_array) \
629 $(arch_errno_name_array) 636 $(arch_errno_name_array)
@@ -923,6 +930,7 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea
923 $(OUTPUT)$(vhost_virtio_ioctl_array) \ 930 $(OUTPUT)$(vhost_virtio_ioctl_array) \
924 $(OUTPUT)$(perf_ioctl_array) \ 931 $(OUTPUT)$(perf_ioctl_array) \
925 $(OUTPUT)$(prctl_option_array) \ 932 $(OUTPUT)$(prctl_option_array) \
933 $(OUTPUT)$(usbdevfs_ioctl_array) \
926 $(OUTPUT)$(x86_arch_prctl_code_array) \ 934 $(OUTPUT)$(x86_arch_prctl_code_array) \
927 $(OUTPUT)$(rename_flags_array) \ 935 $(OUTPUT)$(rename_flags_array) \
928 $(OUTPUT)$(arch_errno_name_array) 936 $(OUTPUT)$(arch_errno_name_array)
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index f3aa9d02a5ab..d340d2e42776 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -68,7 +68,7 @@ struct c2c_hist_entry {
68 struct hist_entry he; 68 struct hist_entry he;
69}; 69};
70 70
71static char const *coalesce_default = "pid,iaddr"; 71static char const *coalesce_default = "iaddr";
72 72
73struct perf_c2c { 73struct perf_c2c {
74 struct perf_tool tool; 74 struct perf_tool tool;
@@ -1878,7 +1878,7 @@ static int c2c_hists__reinit(struct c2c_hists *c2c_hists,
1878 return hpp_list__parse(&c2c_hists->list, output, sort); 1878 return hpp_list__parse(&c2c_hists->list, output, sort);
1879} 1879}
1880 1880
1881#define DISPLAY_LINE_LIMIT 0.0005 1881#define DISPLAY_LINE_LIMIT 0.001
1882 1882
1883static bool he__display(struct hist_entry *he, struct c2c_stats *stats) 1883static bool he__display(struct hist_entry *he, struct c2c_stats *stats)
1884{ 1884{
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 3728b50e52e2..d079f36d342d 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1073,9 +1073,18 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
1073 1073
1074 /* 1074 /*
1075 * Print final block upto sample 1075 * Print final block upto sample
1076 *
1077 * Due to pipeline delays the LBRs might be missing a branch
1078 * or two, which can result in very large or negative blocks
1079 * between final branch and sample. When this happens just
1080 * continue walking after the last TO until we hit a branch.
1076 */ 1081 */
1077 start = br->entries[0].to; 1082 start = br->entries[0].to;
1078 end = sample->ip; 1083 end = sample->ip;
1084 if (end < start) {
1085 /* Missing jump. Scan 128 bytes for the next branch */
1086 end = start + 128;
1087 }
1079 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, true); 1088 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, true);
1080 printed += ip__fprintf_sym(start, thread, x.cpumode, x.cpu, &lastsym, attr, fp); 1089 printed += ip__fprintf_sym(start, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
1081 if (len <= 0) { 1090 if (len <= 0) {
@@ -1084,7 +1093,6 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
1084 machine, thread, &x.is64bit, &x.cpumode, false); 1093 machine, thread, &x.is64bit, &x.cpumode, false);
1085 if (len <= 0) 1094 if (len <= 0)
1086 goto out; 1095 goto out;
1087
1088 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", sample->ip, 1096 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", sample->ip,
1089 dump_insn(&x, sample->ip, buffer, len, NULL)); 1097 dump_insn(&x, sample->ip, buffer, len, NULL));
1090 if (PRINT_FIELD(SRCCODE)) 1098 if (PRINT_FIELD(SRCCODE))
@@ -1096,6 +1104,13 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
1096 dump_insn(&x, start + off, buffer + off, len - off, &ilen)); 1104 dump_insn(&x, start + off, buffer + off, len - off, &ilen));
1097 if (ilen == 0) 1105 if (ilen == 0)
1098 break; 1106 break;
1107 if (arch_is_branch(buffer + off, len - off, x.is64bit) && start + off != sample->ip) {
1108 /*
1109 * Hit a missing branch. Just stop.
1110 */
1111 printed += fprintf(fp, "\t... not reaching sample ...\n");
1112 break;
1113 }
1099 if (PRINT_FIELD(SRCCODE)) 1114 if (PRINT_FIELD(SRCCODE))
1100 print_srccode(thread, x.cpumode, start + off); 1115 print_srccode(thread, x.cpumode, start + off);
1101 } 1116 }
@@ -1167,7 +1182,7 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1167 struct addr_location *al, FILE *fp) 1182 struct addr_location *al, FILE *fp)
1168{ 1183{
1169 struct perf_event_attr *attr = &evsel->attr; 1184 struct perf_event_attr *attr = &evsel->attr;
1170 size_t depth = thread_stack__depth(thread); 1185 size_t depth = thread_stack__depth(thread, sample->cpu);
1171 const char *name = NULL; 1186 const char *name = NULL;
1172 static int spacing; 1187 static int spacing;
1173 int len = 0; 1188 int len = 0;
@@ -1701,7 +1716,7 @@ static bool show_event(struct perf_sample *sample,
1701 struct thread *thread, 1716 struct thread *thread,
1702 struct addr_location *al) 1717 struct addr_location *al)
1703{ 1718{
1704 int depth = thread_stack__depth(thread); 1719 int depth = thread_stack__depth(thread, sample->cpu);
1705 1720
1706 if (!symbol_conf.graph_function) 1721 if (!symbol_conf.graph_function)
1707 return true; 1722 return true;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index ebde59e61133..adbf28183560 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -60,6 +60,7 @@
60#include <linux/stringify.h> 60#include <linux/stringify.h>
61#include <linux/time64.h> 61#include <linux/time64.h>
62#include <fcntl.h> 62#include <fcntl.h>
63#include <sys/sysmacros.h>
63 64
64#include "sane_ctype.h" 65#include "sane_ctype.h"
65 66
@@ -112,8 +113,9 @@ struct trace {
112 } stats; 113 } stats;
113 unsigned int max_stack; 114 unsigned int max_stack;
114 unsigned int min_stack; 115 unsigned int min_stack;
115 bool sort_events; 116 int raw_augmented_syscalls_args_size;
116 bool raw_augmented_syscalls; 117 bool raw_augmented_syscalls;
118 bool sort_events;
117 bool not_ev_qualifier; 119 bool not_ev_qualifier;
118 bool live; 120 bool live;
119 bool full_time; 121 bool full_time;
@@ -283,12 +285,17 @@ out_delete:
283 return -ENOENT; 285 return -ENOENT;
284} 286}
285 287
286static int perf_evsel__init_augmented_syscall_tp(struct perf_evsel *evsel) 288static int perf_evsel__init_augmented_syscall_tp(struct perf_evsel *evsel, struct perf_evsel *tp)
287{ 289{
288 struct syscall_tp *sc = evsel->priv = malloc(sizeof(struct syscall_tp)); 290 struct syscall_tp *sc = evsel->priv = malloc(sizeof(struct syscall_tp));
289 291
290 if (evsel->priv != NULL) { /* field, sizeof_field, offsetof_field */ 292 if (evsel->priv != NULL) {
291 if (__tp_field__init_uint(&sc->id, sizeof(long), sizeof(long long), evsel->needs_swap)) 293 struct tep_format_field *syscall_id = perf_evsel__field(tp, "id");
294 if (syscall_id == NULL)
295 syscall_id = perf_evsel__field(tp, "__syscall_nr");
296 if (syscall_id == NULL)
297 goto out_delete;
298 if (__tp_field__init_uint(&sc->id, syscall_id->size, syscall_id->offset, evsel->needs_swap))
292 goto out_delete; 299 goto out_delete;
293 300
294 return 0; 301 return 0;
@@ -974,9 +981,9 @@ struct thread_trace {
974 char *name; 981 char *name;
975 } filename; 982 } filename;
976 struct { 983 struct {
977 int max; 984 int max;
978 char **table; 985 struct file *table;
979 } paths; 986 } files;
980 987
981 struct intlist *syscall_stats; 988 struct intlist *syscall_stats;
982}; 989};
@@ -986,7 +993,7 @@ static struct thread_trace *thread_trace__new(void)
986 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace)); 993 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
987 994
988 if (ttrace) 995 if (ttrace)
989 ttrace->paths.max = -1; 996 ttrace->files.max = -1;
990 997
991 ttrace->syscall_stats = intlist__new(NULL); 998 ttrace->syscall_stats = intlist__new(NULL);
992 999
@@ -1030,30 +1037,48 @@ void syscall_arg__set_ret_scnprintf(struct syscall_arg *arg,
1030 1037
1031static const size_t trace__entry_str_size = 2048; 1038static const size_t trace__entry_str_size = 2048;
1032 1039
1033static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname) 1040static struct file *thread_trace__files_entry(struct thread_trace *ttrace, int fd)
1034{ 1041{
1035 struct thread_trace *ttrace = thread__priv(thread); 1042 if (fd > ttrace->files.max) {
1036 1043 struct file *nfiles = realloc(ttrace->files.table, (fd + 1) * sizeof(struct file));
1037 if (fd > ttrace->paths.max) {
1038 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
1039 1044
1040 if (npath == NULL) 1045 if (nfiles == NULL)
1041 return -1; 1046 return NULL;
1042 1047
1043 if (ttrace->paths.max != -1) { 1048 if (ttrace->files.max != -1) {
1044 memset(npath + ttrace->paths.max + 1, 0, 1049 memset(nfiles + ttrace->files.max + 1, 0,
1045 (fd - ttrace->paths.max) * sizeof(char *)); 1050 (fd - ttrace->files.max) * sizeof(struct file));
1046 } else { 1051 } else {
1047 memset(npath, 0, (fd + 1) * sizeof(char *)); 1052 memset(nfiles, 0, (fd + 1) * sizeof(struct file));
1048 } 1053 }
1049 1054
1050 ttrace->paths.table = npath; 1055 ttrace->files.table = nfiles;
1051 ttrace->paths.max = fd; 1056 ttrace->files.max = fd;
1052 } 1057 }
1053 1058
1054 ttrace->paths.table[fd] = strdup(pathname); 1059 return ttrace->files.table + fd;
1060}
1055 1061
1056 return ttrace->paths.table[fd] != NULL ? 0 : -1; 1062struct file *thread__files_entry(struct thread *thread, int fd)
1063{
1064 return thread_trace__files_entry(thread__priv(thread), fd);
1065}
1066
1067static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
1068{
1069 struct thread_trace *ttrace = thread__priv(thread);
1070 struct file *file = thread_trace__files_entry(ttrace, fd);
1071
1072 if (file != NULL) {
1073 struct stat st;
1074 if (stat(pathname, &st) == 0)
1075 file->dev_maj = major(st.st_rdev);
1076 file->pathname = strdup(pathname);
1077 if (file->pathname)
1078 return 0;
1079 }
1080
1081 return -1;
1057} 1082}
1058 1083
1059static int thread__read_fd_path(struct thread *thread, int fd) 1084static int thread__read_fd_path(struct thread *thread, int fd)
@@ -1093,7 +1118,7 @@ static const char *thread__fd_path(struct thread *thread, int fd,
1093 if (fd < 0) 1118 if (fd < 0)
1094 return NULL; 1119 return NULL;
1095 1120
1096 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL)) { 1121 if ((fd > ttrace->files.max || ttrace->files.table[fd].pathname == NULL)) {
1097 if (!trace->live) 1122 if (!trace->live)
1098 return NULL; 1123 return NULL;
1099 ++trace->stats.proc_getname; 1124 ++trace->stats.proc_getname;
@@ -1101,7 +1126,7 @@ static const char *thread__fd_path(struct thread *thread, int fd,
1101 return NULL; 1126 return NULL;
1102 } 1127 }
1103 1128
1104 return ttrace->paths.table[fd]; 1129 return ttrace->files.table[fd].pathname;
1105} 1130}
1106 1131
1107size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg) 1132size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg)
@@ -1140,8 +1165,8 @@ static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1140 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg); 1165 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
1141 struct thread_trace *ttrace = thread__priv(arg->thread); 1166 struct thread_trace *ttrace = thread__priv(arg->thread);
1142 1167
1143 if (ttrace && fd >= 0 && fd <= ttrace->paths.max) 1168 if (ttrace && fd >= 0 && fd <= ttrace->files.max)
1144 zfree(&ttrace->paths.table[fd]); 1169 zfree(&ttrace->files.table[fd].pathname);
1145 1170
1146 return printed; 1171 return printed;
1147} 1172}
@@ -1768,16 +1793,16 @@ static int trace__fprintf_sample(struct trace *trace, struct perf_evsel *evsel,
1768 return printed; 1793 return printed;
1769} 1794}
1770 1795
1771static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sample, int *augmented_args_size, bool raw_augmented) 1796static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sample, int *augmented_args_size, int raw_augmented_args_size)
1772{ 1797{
1773 void *augmented_args = NULL; 1798 void *augmented_args = NULL;
1774 /* 1799 /*
1775 * For now with BPF raw_augmented we hook into raw_syscalls:sys_enter 1800 * For now with BPF raw_augmented we hook into raw_syscalls:sys_enter
1776 * and there we get all 6 syscall args plus the tracepoint common 1801 * and there we get all 6 syscall args plus the tracepoint common fields
1777 * fields (sizeof(long)) and the syscall_nr (another long). So we check 1802 * that gets calculated at the start and the syscall_nr (another long).
1778 * if that is the case and if so don't look after the sc->args_size, 1803 * So we check if that is the case and if so don't look after the
1779 * but always after the full raw_syscalls:sys_enter payload, which is 1804 * sc->args_size but always after the full raw_syscalls:sys_enter payload,
1780 * fixed. 1805 * which is fixed.
1781 * 1806 *
1782 * We'll revisit this later to pass s->args_size to the BPF augmenter 1807 * We'll revisit this later to pass s->args_size to the BPF augmenter
1783 * (now tools/perf/examples/bpf/augmented_raw_syscalls.c, so that it 1808 * (now tools/perf/examples/bpf/augmented_raw_syscalls.c, so that it
@@ -1785,7 +1810,7 @@ static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sam
1785 * use syscalls:sys_enter_NAME, so that we reduce the kernel/userspace 1810 * use syscalls:sys_enter_NAME, so that we reduce the kernel/userspace
1786 * traffic to just what is needed for each syscall. 1811 * traffic to just what is needed for each syscall.
1787 */ 1812 */
1788 int args_size = raw_augmented ? (8 * (int)sizeof(long)) : sc->args_size; 1813 int args_size = raw_augmented_args_size ?: sc->args_size;
1789 1814
1790 *augmented_args_size = sample->raw_size - args_size; 1815 *augmented_args_size = sample->raw_size - args_size;
1791 if (*augmented_args_size > 0) 1816 if (*augmented_args_size > 0)
@@ -1839,7 +1864,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1839 * here and avoid using augmented syscalls when the evsel is the raw_syscalls one. 1864 * here and avoid using augmented syscalls when the evsel is the raw_syscalls one.
1840 */ 1865 */
1841 if (evsel != trace->syscalls.events.sys_enter) 1866 if (evsel != trace->syscalls.events.sys_enter)
1842 augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size, trace->raw_augmented_syscalls); 1867 augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size, trace->raw_augmented_syscalls_args_size);
1843 ttrace->entry_time = sample->time; 1868 ttrace->entry_time = sample->time;
1844 msg = ttrace->entry_str; 1869 msg = ttrace->entry_str;
1845 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name); 1870 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name);
@@ -1897,7 +1922,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct perf_evsel *evse
1897 goto out_put; 1922 goto out_put;
1898 1923
1899 args = perf_evsel__sc_tp_ptr(evsel, args, sample); 1924 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
1900 augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size, trace->raw_augmented_syscalls); 1925 augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size, trace->raw_augmented_syscalls_args_size);
1901 syscall__scnprintf_args(sc, msg, sizeof(msg), args, augmented_args, augmented_args_size, trace, thread); 1926 syscall__scnprintf_args(sc, msg, sizeof(msg), args, augmented_args, augmented_args_size, trace, thread);
1902 fprintf(trace->output, "%s", msg); 1927 fprintf(trace->output, "%s", msg);
1903 err = 0; 1928 err = 0;
@@ -2686,7 +2711,9 @@ static int trace__set_ev_qualifier_filter(struct trace *trace)
2686{ 2711{
2687 if (trace->syscalls.map) 2712 if (trace->syscalls.map)
2688 return trace__set_ev_qualifier_bpf_filter(trace); 2713 return trace__set_ev_qualifier_bpf_filter(trace);
2689 return trace__set_ev_qualifier_tp_filter(trace); 2714 if (trace->syscalls.events.sys_enter)
2715 return trace__set_ev_qualifier_tp_filter(trace);
2716 return 0;
2690} 2717}
2691 2718
2692static int bpf_map__set_filter_pids(struct bpf_map *map __maybe_unused, 2719static int bpf_map__set_filter_pids(struct bpf_map *map __maybe_unused,
@@ -3812,13 +3839,6 @@ int cmd_trace(int argc, const char **argv)
3812 * syscall. 3839 * syscall.
3813 */ 3840 */
3814 if (trace.syscalls.events.augmented) { 3841 if (trace.syscalls.events.augmented) {
3815 evsel = trace.syscalls.events.augmented;
3816
3817 if (perf_evsel__init_augmented_syscall_tp(evsel) ||
3818 perf_evsel__init_augmented_syscall_tp_args(evsel))
3819 goto out;
3820 evsel->handler = trace__sys_enter;
3821
3822 evlist__for_each_entry(trace.evlist, evsel) { 3842 evlist__for_each_entry(trace.evlist, evsel) {
3823 bool raw_syscalls_sys_exit = strcmp(perf_evsel__name(evsel), "raw_syscalls:sys_exit") == 0; 3843 bool raw_syscalls_sys_exit = strcmp(perf_evsel__name(evsel), "raw_syscalls:sys_exit") == 0;
3824 3844
@@ -3827,9 +3847,41 @@ int cmd_trace(int argc, const char **argv)
3827 goto init_augmented_syscall_tp; 3847 goto init_augmented_syscall_tp;
3828 } 3848 }
3829 3849
3850 if (strcmp(perf_evsel__name(evsel), "raw_syscalls:sys_enter") == 0) {
3851 struct perf_evsel *augmented = trace.syscalls.events.augmented;
3852 if (perf_evsel__init_augmented_syscall_tp(augmented, evsel) ||
3853 perf_evsel__init_augmented_syscall_tp_args(augmented))
3854 goto out;
3855 augmented->handler = trace__sys_enter;
3856 }
3857
3830 if (strstarts(perf_evsel__name(evsel), "syscalls:sys_exit_")) { 3858 if (strstarts(perf_evsel__name(evsel), "syscalls:sys_exit_")) {
3859 struct syscall_tp *sc;
3831init_augmented_syscall_tp: 3860init_augmented_syscall_tp:
3832 perf_evsel__init_augmented_syscall_tp(evsel); 3861 if (perf_evsel__init_augmented_syscall_tp(evsel, evsel))
3862 goto out;
3863 sc = evsel->priv;
3864 /*
3865 * For now with BPF raw_augmented we hook into
3866 * raw_syscalls:sys_enter and there we get all
3867 * 6 syscall args plus the tracepoint common
3868 * fields and the syscall_nr (another long).
3869 * So we check if that is the case and if so
3870 * don't look after the sc->args_size but
3871 * always after the full raw_syscalls:sys_enter
3872 * payload, which is fixed.
3873 *
3874 * We'll revisit this later to pass
3875 * s->args_size to the BPF augmenter (now
3876 * tools/perf/examples/bpf/augmented_raw_syscalls.c,
3877 * so that it copies only what we need for each
3878 * syscall, like what happens when we use
3879 * syscalls:sys_enter_NAME, so that we reduce
3880 * the kernel/userspace traffic to just what is
3881 * needed for each syscall.
3882 */
3883 if (trace.raw_augmented_syscalls)
3884 trace.raw_augmented_syscalls_args_size = (6 + 1) * sizeof(long) + sc->id.offset;
3833 perf_evsel__init_augmented_syscall_tp_ret(evsel); 3885 perf_evsel__init_augmented_syscall_tp_ret(evsel);
3834 evsel->handler = trace__sys_exit; 3886 evsel->handler = trace__sys_exit;
3835 } 3887 }
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index 8e811ea0cf85..6cb98f8570a2 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -14,6 +14,7 @@ include/uapi/linux/perf_event.h
14include/uapi/linux/prctl.h 14include/uapi/linux/prctl.h
15include/uapi/linux/sched.h 15include/uapi/linux/sched.h
16include/uapi/linux/stat.h 16include/uapi/linux/stat.h
17include/uapi/linux/usbdevice_fs.h
17include/uapi/linux/vhost.h 18include/uapi/linux/vhost.h
18include/uapi/sound/asound.h 19include/uapi/sound/asound.h
19include/linux/bits.h 20include/linux/bits.h
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index 83c5b202e00e..139d485a6f16 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -32,6 +32,13 @@ size_t strarray__scnprintf_flags(struct strarray *sa, char *bf, size_t size, boo
32struct trace; 32struct trace;
33struct thread; 33struct thread;
34 34
35struct file {
36 char *pathname;
37 int dev_maj;
38};
39
40struct file *thread__files_entry(struct thread *thread, int fd);
41
35struct strarrays { 42struct strarrays {
36 int nr_entries; 43 int nr_entries;
37 struct strarray **entries; 44 struct strarray **entries;
diff --git a/tools/perf/trace/beauty/ioctl.c b/tools/perf/trace/beauty/ioctl.c
index 9efeb6a936c2..620350d41209 100644
--- a/tools/perf/trace/beauty/ioctl.c
+++ b/tools/perf/trace/beauty/ioctl.c
@@ -112,6 +112,17 @@ static size_t ioctl__scnprintf_perf_cmd(int nr, int dir, char *bf, size_t size)
112 return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAE, nr, dir); 112 return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAE, nr, dir);
113} 113}
114 114
115static size_t ioctl__scnprintf_usbdevfs_cmd(int nr, int dir, char *bf, size_t size)
116{
117#include "trace/beauty/generated/ioctl/usbdevfs_ioctl_array.c"
118 static DEFINE_STRARRAY(usbdevfs_ioctl_cmds, "");
119
120 if (nr < strarray__usbdevfs_ioctl_cmds.nr_entries && strarray__usbdevfs_ioctl_cmds.entries[nr] != NULL)
121 return scnprintf(bf, size, "USBDEVFS_%s", strarray__usbdevfs_ioctl_cmds.entries[nr]);
122
123 return scnprintf(bf, size, "(%c, %#x, %#x)", 'U', nr, dir);
124}
125
115static size_t ioctl__scnprintf_cmd(unsigned long cmd, char *bf, size_t size, bool show_prefix) 126static size_t ioctl__scnprintf_cmd(unsigned long cmd, char *bf, size_t size, bool show_prefix)
116{ 127{
117 const char *prefix = "_IOC_"; 128 const char *prefix = "_IOC_";
@@ -157,9 +168,20 @@ static size_t ioctl__scnprintf_cmd(unsigned long cmd, char *bf, size_t size, boo
157 return printed + scnprintf(bf + printed, size - printed, ", %#x, %#x, %#x)", type, nr, sz); 168 return printed + scnprintf(bf + printed, size - printed, ", %#x, %#x, %#x)", type, nr, sz);
158} 169}
159 170
171#ifndef USB_DEVICE_MAJOR
172#define USB_DEVICE_MAJOR 189
173#endif // USB_DEVICE_MAJOR
174
160size_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_arg *arg) 175size_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_arg *arg)
161{ 176{
162 unsigned long cmd = arg->val; 177 unsigned long cmd = arg->val;
178 unsigned int fd = syscall_arg__val(arg, 0);
179 struct file *file = thread__files_entry(arg->thread, fd);
180
181 if (file != NULL) {
182 if (file->dev_maj == USB_DEVICE_MAJOR)
183 return ioctl__scnprintf_usbdevfs_cmd(_IOC_NR(cmd), _IOC_DIR(cmd), bf, size);
184 }
163 185
164 return ioctl__scnprintf_cmd(cmd, bf, size, arg->show_string_prefix); 186 return ioctl__scnprintf_cmd(cmd, bf, size, arg->show_string_prefix);
165} 187}
diff --git a/tools/perf/trace/beauty/mmap.c b/tools/perf/trace/beauty/mmap.c
index eb31089790e3..859a8a9db2c6 100644
--- a/tools/perf/trace/beauty/mmap.c
+++ b/tools/perf/trace/beauty/mmap.c
@@ -18,8 +18,8 @@ static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
18 } 18 }
19 19
20 P_MMAP_PROT(READ); 20 P_MMAP_PROT(READ);
21 P_MMAP_PROT(EXEC);
22 P_MMAP_PROT(WRITE); 21 P_MMAP_PROT(WRITE);
22 P_MMAP_PROT(EXEC);
23 P_MMAP_PROT(SEM); 23 P_MMAP_PROT(SEM);
24 P_MMAP_PROT(GROWSDOWN); 24 P_MMAP_PROT(GROWSDOWN);
25 P_MMAP_PROT(GROWSUP); 25 P_MMAP_PROT(GROWSUP);
diff --git a/tools/perf/trace/beauty/seccomp.c b/tools/perf/trace/beauty/seccomp.c
index 4600c28a3cfe..637722e2796b 100644
--- a/tools/perf/trace/beauty/seccomp.c
+++ b/tools/perf/trace/beauty/seccomp.c
@@ -9,7 +9,7 @@
9static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg) 9static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg)
10{ 10{
11 bool show_prefix = arg->show_string_prefix; 11 bool show_prefix = arg->show_string_prefix;
12 const char *prefix = "SECOMP_SET_MODE_"; 12 const char *prefix = "SECCOMP_SET_MODE_";
13 int op = arg->val; 13 int op = arg->val;
14 size_t printed = 0; 14 size_t printed = 0;
15 15
@@ -34,7 +34,7 @@ static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size,
34 struct syscall_arg *arg) 34 struct syscall_arg *arg)
35{ 35{
36 bool show_prefix = arg->show_string_prefix; 36 bool show_prefix = arg->show_string_prefix;
37 const char *prefix = "SECOMP_FILTER_FLAG_"; 37 const char *prefix = "SECCOMP_FILTER_FLAG_";
38 int printed = 0, flags = arg->val; 38 int printed = 0, flags = arg->val;
39 39
40#define P_FLAG(n) \ 40#define P_FLAG(n) \
diff --git a/tools/perf/trace/beauty/usbdevfs_ioctl.sh b/tools/perf/trace/beauty/usbdevfs_ioctl.sh
new file mode 100755
index 000000000000..930b80f422e8
--- /dev/null
+++ b/tools/perf/trace/beauty/usbdevfs_ioctl.sh
@@ -0,0 +1,19 @@
1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
3
4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
5
6printf "static const char *usbdevfs_ioctl_cmds[] = {\n"
7regex="^#[[:space:]]*define[[:space:]]+USBDEVFS_(\w+)[[:space:]]+_IO[WR]{0,2}\([[:space:]]*'U'[[:space:]]*,[[:space:]]*([[:digit:]]+).*"
8egrep $regex ${header_dir}/usbdevice_fs.h | egrep -v 'USBDEVFS_\w+32[[:space:]]' | \
9 sed -r "s/$regex/\2 \1/g" | \
10 sort | xargs printf "\t[%s] = \"%s\",\n"
11printf "};\n\n"
12printf "#if 0\n"
13printf "static const char *usbdevfs_ioctl_32_cmds[] = {\n"
14regex="^#[[:space:]]*define[[:space:]]+USBDEVFS_(\w+)[[:space:]]+_IO[WR]{0,2}\([[:space:]]*'U'[[:space:]]*,[[:space:]]*([[:digit:]]+).*"
15egrep $regex ${header_dir}/usbdevice_fs.h | egrep 'USBDEVFS_\w+32[[:space:]]' | \
16 sed -r "s/$regex/\2 \1/g" | \
17 sort | xargs printf "\t[%s] = \"%s\",\n"
18printf "};\n"
19printf "#endif\n"
diff --git a/tools/perf/util/dump-insn.c b/tools/perf/util/dump-insn.c
index 10988d3de7ce..2bd8585db93c 100644
--- a/tools/perf/util/dump-insn.c
+++ b/tools/perf/util/dump-insn.c
@@ -13,3 +13,11 @@ const char *dump_insn(struct perf_insn *x __maybe_unused,
13 *lenp = 0; 13 *lenp = 0;
14 return "?"; 14 return "?";
15} 15}
16
17__weak
18int arch_is_branch(const unsigned char *buf __maybe_unused,
19 size_t len __maybe_unused,
20 int x86_64 __maybe_unused)
21{
22 return 0;
23}
diff --git a/tools/perf/util/dump-insn.h b/tools/perf/util/dump-insn.h
index 0e06280a8860..650125061530 100644
--- a/tools/perf/util/dump-insn.h
+++ b/tools/perf/util/dump-insn.h
@@ -20,4 +20,6 @@ struct perf_insn {
20 20
21const char *dump_insn(struct perf_insn *x, u64 ip, 21const char *dump_insn(struct perf_insn *x, u64 ip,
22 u8 *inbuf, int inlen, int *lenp); 22 u8 *inbuf, int inlen, int *lenp);
23int arch_is_branch(const unsigned char *buf, size_t len, int x86_64);
24
23#endif 25#endif
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index 7b27d77306c2..ee6ca65f81f4 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -451,7 +451,7 @@ static int intel_bts_process_buffer(struct intel_bts_queue *btsq,
451 continue; 451 continue;
452 intel_bts_get_branch_type(btsq, branch); 452 intel_bts_get_branch_type(btsq, branch);
453 if (btsq->bts->synth_opts.thread_stack) 453 if (btsq->bts->synth_opts.thread_stack)
454 thread_stack__event(thread, btsq->sample_flags, 454 thread_stack__event(thread, btsq->cpu, btsq->sample_flags,
455 le64_to_cpu(branch->from), 455 le64_to_cpu(branch->from),
456 le64_to_cpu(branch->to), 456 le64_to_cpu(branch->to),
457 btsq->intel_pt_insn.length, 457 btsq->intel_pt_insn.length,
@@ -523,7 +523,7 @@ static int intel_bts_process_queue(struct intel_bts_queue *btsq, u64 *timestamp)
523 !btsq->bts->synth_opts.thread_stack && thread && 523 !btsq->bts->synth_opts.thread_stack && thread &&
524 (!old_buffer || btsq->bts->sampling_mode || 524 (!old_buffer || btsq->bts->sampling_mode ||
525 (btsq->bts->snapshot_mode && !buffer->consecutive))) 525 (btsq->bts->snapshot_mode && !buffer->consecutive)))
526 thread_stack__set_trace_nr(thread, buffer->buffer_nr + 1); 526 thread_stack__set_trace_nr(thread, btsq->cpu, buffer->buffer_nr + 1);
527 527
528 err = intel_bts_process_buffer(btsq, buffer, thread); 528 err = intel_bts_process_buffer(btsq, buffer, thread);
529 529
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
index 54818828023b..1c0e289f01e6 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
@@ -180,6 +180,14 @@ int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64,
180 return 0; 180 return 0;
181} 181}
182 182
183int arch_is_branch(const unsigned char *buf, size_t len, int x86_64)
184{
185 struct intel_pt_insn in;
186 if (intel_pt_get_insn(buf, len, x86_64, &in) < 0)
187 return -1;
188 return in.branch != INTEL_PT_BR_NO_BRANCH;
189}
190
183const char *dump_insn(struct perf_insn *x, uint64_t ip __maybe_unused, 191const char *dump_insn(struct perf_insn *x, uint64_t ip __maybe_unused,
184 u8 *inbuf, int inlen, int *lenp) 192 u8 *inbuf, int inlen, int *lenp)
185{ 193{
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 149ff361ca78..2e72373ec6df 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1174,7 +1174,7 @@ static void intel_pt_prep_sample(struct intel_pt *pt,
1174 intel_pt_prep_b_sample(pt, ptq, event, sample); 1174 intel_pt_prep_b_sample(pt, ptq, event, sample);
1175 1175
1176 if (pt->synth_opts.callchain) { 1176 if (pt->synth_opts.callchain) {
1177 thread_stack__sample(ptq->thread, ptq->chain, 1177 thread_stack__sample(ptq->thread, ptq->cpu, ptq->chain,
1178 pt->synth_opts.callchain_sz + 1, 1178 pt->synth_opts.callchain_sz + 1,
1179 sample->ip, pt->kernel_start); 1179 sample->ip, pt->kernel_start);
1180 sample->callchain = ptq->chain; 1180 sample->callchain = ptq->chain;
@@ -1526,11 +1526,11 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
1526 return 0; 1526 return 0;
1527 1527
1528 if (pt->synth_opts.callchain || pt->synth_opts.thread_stack) 1528 if (pt->synth_opts.callchain || pt->synth_opts.thread_stack)
1529 thread_stack__event(ptq->thread, ptq->flags, state->from_ip, 1529 thread_stack__event(ptq->thread, ptq->cpu, ptq->flags, state->from_ip,
1530 state->to_ip, ptq->insn_len, 1530 state->to_ip, ptq->insn_len,
1531 state->trace_nr); 1531 state->trace_nr);
1532 else 1532 else
1533 thread_stack__set_trace_nr(ptq->thread, state->trace_nr); 1533 thread_stack__set_trace_nr(ptq->thread, ptq->cpu, state->trace_nr);
1534 1534
1535 if (pt->sample_branches) { 1535 if (pt->sample_branches) {
1536 err = intel_pt_synth_branch_sample(ptq); 1536 err = intel_pt_synth_branch_sample(ptq);
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 47628e85c5eb..dda0ac978b1e 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -939,7 +939,8 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
939 939
940 file = PyFile_FromFile(fp, "perf", "r", NULL); 940 file = PyFile_FromFile(fp, "perf", "r", NULL);
941#else 941#else
942 file = PyFile_FromFd(evlist->pollfd.entries[i].fd, "perf", "r", -1, NULL, NULL, NULL, 1); 942 file = PyFile_FromFd(evlist->pollfd.entries[i].fd, "perf", "r", -1,
943 NULL, NULL, NULL, 0);
943#endif 944#endif
944 if (file == NULL) 945 if (file == NULL)
945 goto free_list; 946 goto free_list;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 78a067777144..5456c84c7dd1 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1527,6 +1527,13 @@ struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
1527 return machine__findnew_thread(&session->machines.host, -1, pid); 1527 return machine__findnew_thread(&session->machines.host, -1, pid);
1528} 1528}
1529 1529
1530/*
1531 * Threads are identified by pid and tid, and the idle task has pid == tid == 0.
1532 * So here a single thread is created for that, but actually there is a separate
1533 * idle task per cpu, so there should be one 'struct thread' per cpu, but there
1534 * is only 1. That causes problems for some tools, requiring workarounds. For
1535 * example get_idle_thread() in builtin-sched.c, or thread_stack__per_cpu().
1536 */
1530int perf_session__register_idle_thread(struct perf_session *session) 1537int perf_session__register_idle_thread(struct perf_session *session)
1531{ 1538{
1532 struct thread *thread; 1539 struct thread *thread;
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
index 61a4286a74dc..d52f27f373ce 100644
--- a/tools/perf/util/thread-stack.c
+++ b/tools/perf/util/thread-stack.c
@@ -15,6 +15,7 @@
15 15
16#include <linux/rbtree.h> 16#include <linux/rbtree.h>
17#include <linux/list.h> 17#include <linux/list.h>
18#include <linux/log2.h>
18#include <errno.h> 19#include <errno.h>
19#include "thread.h" 20#include "thread.h"
20#include "event.h" 21#include "event.h"
@@ -60,6 +61,7 @@ struct thread_stack_entry {
60 * @last_time: last timestamp 61 * @last_time: last timestamp
61 * @crp: call/return processor 62 * @crp: call/return processor
62 * @comm: current comm 63 * @comm: current comm
64 * @arr_sz: size of array if this is the first element of an array
63 */ 65 */
64struct thread_stack { 66struct thread_stack {
65 struct thread_stack_entry *stack; 67 struct thread_stack_entry *stack;
@@ -71,8 +73,19 @@ struct thread_stack {
71 u64 last_time; 73 u64 last_time;
72 struct call_return_processor *crp; 74 struct call_return_processor *crp;
73 struct comm *comm; 75 struct comm *comm;
76 unsigned int arr_sz;
74}; 77};
75 78
79/*
80 * Assume pid == tid == 0 identifies the idle task as defined by
81 * perf_session__register_idle_thread(). The idle task is really 1 task per cpu,
82 * and therefore requires a stack for each cpu.
83 */
84static inline bool thread_stack__per_cpu(struct thread *thread)
85{
86 return !(thread->tid || thread->pid_);
87}
88
76static int thread_stack__grow(struct thread_stack *ts) 89static int thread_stack__grow(struct thread_stack *ts)
77{ 90{
78 struct thread_stack_entry *new_stack; 91 struct thread_stack_entry *new_stack;
@@ -91,19 +104,14 @@ static int thread_stack__grow(struct thread_stack *ts)
91 return 0; 104 return 0;
92} 105}
93 106
94static struct thread_stack *thread_stack__new(struct thread *thread, 107static int thread_stack__init(struct thread_stack *ts, struct thread *thread,
95 struct call_return_processor *crp) 108 struct call_return_processor *crp)
96{ 109{
97 struct thread_stack *ts; 110 int err;
98
99 ts = zalloc(sizeof(struct thread_stack));
100 if (!ts)
101 return NULL;
102 111
103 if (thread_stack__grow(ts)) { 112 err = thread_stack__grow(ts);
104 free(ts); 113 if (err)
105 return NULL; 114 return err;
106 }
107 115
108 if (thread->mg && thread->mg->machine) 116 if (thread->mg && thread->mg->machine)
109 ts->kernel_start = machine__kernel_start(thread->mg->machine); 117 ts->kernel_start = machine__kernel_start(thread->mg->machine);
@@ -111,9 +119,72 @@ static struct thread_stack *thread_stack__new(struct thread *thread,
111 ts->kernel_start = 1ULL << 63; 119 ts->kernel_start = 1ULL << 63;
112 ts->crp = crp; 120 ts->crp = crp;
113 121
122 return 0;
123}
124
125static struct thread_stack *thread_stack__new(struct thread *thread, int cpu,
126 struct call_return_processor *crp)
127{
128 struct thread_stack *ts = thread->ts, *new_ts;
129 unsigned int old_sz = ts ? ts->arr_sz : 0;
130 unsigned int new_sz = 1;
131
132 if (thread_stack__per_cpu(thread) && cpu > 0)
133 new_sz = roundup_pow_of_two(cpu + 1);
134
135 if (!ts || new_sz > old_sz) {
136 new_ts = calloc(new_sz, sizeof(*ts));
137 if (!new_ts)
138 return NULL;
139 if (ts)
140 memcpy(new_ts, ts, old_sz * sizeof(*ts));
141 new_ts->arr_sz = new_sz;
142 zfree(&thread->ts);
143 thread->ts = new_ts;
144 ts = new_ts;
145 }
146
147 if (thread_stack__per_cpu(thread) && cpu > 0 &&
148 (unsigned int)cpu < ts->arr_sz)
149 ts += cpu;
150
151 if (!ts->stack &&
152 thread_stack__init(ts, thread, crp))
153 return NULL;
154
114 return ts; 155 return ts;
115} 156}
116 157
158static struct thread_stack *thread__cpu_stack(struct thread *thread, int cpu)
159{
160 struct thread_stack *ts = thread->ts;
161
162 if (cpu < 0)
163 cpu = 0;
164
165 if (!ts || (unsigned int)cpu >= ts->arr_sz)
166 return NULL;
167
168 ts += cpu;
169
170 if (!ts->stack)
171 return NULL;
172
173 return ts;
174}
175
176static inline struct thread_stack *thread__stack(struct thread *thread,
177 int cpu)
178{
179 if (!thread)
180 return NULL;
181
182 if (thread_stack__per_cpu(thread))
183 return thread__cpu_stack(thread, cpu);
184
185 return thread->ts;
186}
187
117static int thread_stack__push(struct thread_stack *ts, u64 ret_addr, 188static int thread_stack__push(struct thread_stack *ts, u64 ret_addr,
118 bool trace_end) 189 bool trace_end)
119{ 190{
@@ -226,25 +297,37 @@ static int __thread_stack__flush(struct thread *thread, struct thread_stack *ts)
226 297
227int thread_stack__flush(struct thread *thread) 298int thread_stack__flush(struct thread *thread)
228{ 299{
229 if (thread->ts) 300 struct thread_stack *ts = thread->ts;
230 return __thread_stack__flush(thread, thread->ts); 301 unsigned int pos;
302 int err = 0;
231 303
232 return 0; 304 if (ts) {
305 for (pos = 0; pos < ts->arr_sz; pos++) {
306 int ret = __thread_stack__flush(thread, ts + pos);
307
308 if (ret)
309 err = ret;
310 }
311 }
312
313 return err;
233} 314}
234 315
235int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip, 316int thread_stack__event(struct thread *thread, int cpu, u32 flags, u64 from_ip,
236 u64 to_ip, u16 insn_len, u64 trace_nr) 317 u64 to_ip, u16 insn_len, u64 trace_nr)
237{ 318{
319 struct thread_stack *ts = thread__stack(thread, cpu);
320
238 if (!thread) 321 if (!thread)
239 return -EINVAL; 322 return -EINVAL;
240 323
241 if (!thread->ts) { 324 if (!ts) {
242 thread->ts = thread_stack__new(thread, NULL); 325 ts = thread_stack__new(thread, cpu, NULL);
243 if (!thread->ts) { 326 if (!ts) {
244 pr_warning("Out of memory: no thread stack\n"); 327 pr_warning("Out of memory: no thread stack\n");
245 return -ENOMEM; 328 return -ENOMEM;
246 } 329 }
247 thread->ts->trace_nr = trace_nr; 330 ts->trace_nr = trace_nr;
248 } 331 }
249 332
250 /* 333 /*
@@ -252,14 +335,14 @@ int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
252 * the stack might be completely invalid. Better to report nothing than 335 * the stack might be completely invalid. Better to report nothing than
253 * to report something misleading, so flush the stack. 336 * to report something misleading, so flush the stack.
254 */ 337 */
255 if (trace_nr != thread->ts->trace_nr) { 338 if (trace_nr != ts->trace_nr) {
256 if (thread->ts->trace_nr) 339 if (ts->trace_nr)
257 __thread_stack__flush(thread, thread->ts); 340 __thread_stack__flush(thread, ts);
258 thread->ts->trace_nr = trace_nr; 341 ts->trace_nr = trace_nr;
259 } 342 }
260 343
261 /* Stop here if thread_stack__process() is in use */ 344 /* Stop here if thread_stack__process() is in use */
262 if (thread->ts->crp) 345 if (ts->crp)
263 return 0; 346 return 0;
264 347
265 if (flags & PERF_IP_FLAG_CALL) { 348 if (flags & PERF_IP_FLAG_CALL) {
@@ -270,7 +353,7 @@ int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
270 ret_addr = from_ip + insn_len; 353 ret_addr = from_ip + insn_len;
271 if (ret_addr == to_ip) 354 if (ret_addr == to_ip)
272 return 0; /* Zero-length calls are excluded */ 355 return 0; /* Zero-length calls are excluded */
273 return thread_stack__push(thread->ts, ret_addr, 356 return thread_stack__push(ts, ret_addr,
274 flags & PERF_IP_FLAG_TRACE_END); 357 flags & PERF_IP_FLAG_TRACE_END);
275 } else if (flags & PERF_IP_FLAG_TRACE_BEGIN) { 358 } else if (flags & PERF_IP_FLAG_TRACE_BEGIN) {
276 /* 359 /*
@@ -280,32 +363,52 @@ int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
280 * address, so try to pop that. Also, do not expect a call made 363 * address, so try to pop that. Also, do not expect a call made
281 * when the trace ended, to return, so pop that. 364 * when the trace ended, to return, so pop that.
282 */ 365 */
283 thread_stack__pop(thread->ts, to_ip); 366 thread_stack__pop(ts, to_ip);
284 thread_stack__pop_trace_end(thread->ts); 367 thread_stack__pop_trace_end(ts);
285 } else if ((flags & PERF_IP_FLAG_RETURN) && from_ip) { 368 } else if ((flags & PERF_IP_FLAG_RETURN) && from_ip) {
286 thread_stack__pop(thread->ts, to_ip); 369 thread_stack__pop(ts, to_ip);
287 } 370 }
288 371
289 return 0; 372 return 0;
290} 373}
291 374
292void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr) 375void thread_stack__set_trace_nr(struct thread *thread, int cpu, u64 trace_nr)
293{ 376{
294 if (!thread || !thread->ts) 377 struct thread_stack *ts = thread__stack(thread, cpu);
378
379 if (!ts)
295 return; 380 return;
296 381
297 if (trace_nr != thread->ts->trace_nr) { 382 if (trace_nr != ts->trace_nr) {
298 if (thread->ts->trace_nr) 383 if (ts->trace_nr)
299 __thread_stack__flush(thread, thread->ts); 384 __thread_stack__flush(thread, ts);
300 thread->ts->trace_nr = trace_nr; 385 ts->trace_nr = trace_nr;
301 } 386 }
302} 387}
303 388
389static void __thread_stack__free(struct thread *thread, struct thread_stack *ts)
390{
391 __thread_stack__flush(thread, ts);
392 zfree(&ts->stack);
393}
394
395static void thread_stack__reset(struct thread *thread, struct thread_stack *ts)
396{
397 unsigned int arr_sz = ts->arr_sz;
398
399 __thread_stack__free(thread, ts);
400 memset(ts, 0, sizeof(*ts));
401 ts->arr_sz = arr_sz;
402}
403
304void thread_stack__free(struct thread *thread) 404void thread_stack__free(struct thread *thread)
305{ 405{
306 if (thread->ts) { 406 struct thread_stack *ts = thread->ts;
307 __thread_stack__flush(thread, thread->ts); 407 unsigned int pos;
308 zfree(&thread->ts->stack); 408
409 if (ts) {
410 for (pos = 0; pos < ts->arr_sz; pos++)
411 __thread_stack__free(thread, ts + pos);
309 zfree(&thread->ts); 412 zfree(&thread->ts);
310 } 413 }
311} 414}
@@ -315,9 +418,11 @@ static inline u64 callchain_context(u64 ip, u64 kernel_start)
315 return ip < kernel_start ? PERF_CONTEXT_USER : PERF_CONTEXT_KERNEL; 418 return ip < kernel_start ? PERF_CONTEXT_USER : PERF_CONTEXT_KERNEL;
316} 419}
317 420
318void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, 421void thread_stack__sample(struct thread *thread, int cpu,
422 struct ip_callchain *chain,
319 size_t sz, u64 ip, u64 kernel_start) 423 size_t sz, u64 ip, u64 kernel_start)
320{ 424{
425 struct thread_stack *ts = thread__stack(thread, cpu);
321 u64 context = callchain_context(ip, kernel_start); 426 u64 context = callchain_context(ip, kernel_start);
322 u64 last_context; 427 u64 last_context;
323 size_t i, j; 428 size_t i, j;
@@ -330,15 +435,15 @@ void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
330 chain->ips[0] = context; 435 chain->ips[0] = context;
331 chain->ips[1] = ip; 436 chain->ips[1] = ip;
332 437
333 if (!thread || !thread->ts) { 438 if (!ts) {
334 chain->nr = 2; 439 chain->nr = 2;
335 return; 440 return;
336 } 441 }
337 442
338 last_context = context; 443 last_context = context;
339 444
340 for (i = 2, j = 1; i < sz && j <= thread->ts->cnt; i++, j++) { 445 for (i = 2, j = 1; i < sz && j <= ts->cnt; i++, j++) {
341 ip = thread->ts->stack[thread->ts->cnt - j].ret_addr; 446 ip = ts->stack[ts->cnt - j].ret_addr;
342 context = callchain_context(ip, kernel_start); 447 context = callchain_context(ip, kernel_start);
343 if (context != last_context) { 448 if (context != last_context) {
344 if (i >= sz - 1) 449 if (i >= sz - 1)
@@ -449,7 +554,7 @@ static int thread_stack__pop_cp(struct thread *thread, struct thread_stack *ts,
449 return 1; 554 return 1;
450} 555}
451 556
452static int thread_stack__bottom(struct thread *thread, struct thread_stack *ts, 557static int thread_stack__bottom(struct thread_stack *ts,
453 struct perf_sample *sample, 558 struct perf_sample *sample,
454 struct addr_location *from_al, 559 struct addr_location *from_al,
455 struct addr_location *to_al, u64 ref) 560 struct addr_location *to_al, u64 ref)
@@ -474,7 +579,7 @@ static int thread_stack__bottom(struct thread *thread, struct thread_stack *ts,
474 if (!cp) 579 if (!cp)
475 return -ENOMEM; 580 return -ENOMEM;
476 581
477 return thread_stack__push_cp(thread->ts, ip, sample->time, ref, cp, 582 return thread_stack__push_cp(ts, ip, sample->time, ref, cp,
478 true, false); 583 true, false);
479} 584}
480 585
@@ -590,24 +695,19 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
590 struct addr_location *to_al, u64 ref, 695 struct addr_location *to_al, u64 ref,
591 struct call_return_processor *crp) 696 struct call_return_processor *crp)
592{ 697{
593 struct thread_stack *ts = thread->ts; 698 struct thread_stack *ts = thread__stack(thread, sample->cpu);
594 int err = 0; 699 int err = 0;
595 700
596 if (ts) { 701 if (ts && !ts->crp) {
597 if (!ts->crp) { 702 /* Supersede thread_stack__event() */
598 /* Supersede thread_stack__event() */ 703 thread_stack__reset(thread, ts);
599 thread_stack__free(thread); 704 ts = NULL;
600 thread->ts = thread_stack__new(thread, crp); 705 }
601 if (!thread->ts) 706
602 return -ENOMEM; 707 if (!ts) {
603 ts = thread->ts; 708 ts = thread_stack__new(thread, sample->cpu, crp);
604 ts->comm = comm; 709 if (!ts)
605 }
606 } else {
607 thread->ts = thread_stack__new(thread, crp);
608 if (!thread->ts)
609 return -ENOMEM; 710 return -ENOMEM;
610 ts = thread->ts;
611 ts->comm = comm; 711 ts->comm = comm;
612 } 712 }
613 713
@@ -621,8 +721,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
621 721
622 /* If the stack is empty, put the current symbol on the stack */ 722 /* If the stack is empty, put the current symbol on the stack */
623 if (!ts->cnt) { 723 if (!ts->cnt) {
624 err = thread_stack__bottom(thread, ts, sample, from_al, to_al, 724 err = thread_stack__bottom(ts, sample, from_al, to_al, ref);
625 ref);
626 if (err) 725 if (err)
627 return err; 726 return err;
628 } 727 }
@@ -671,9 +770,11 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
671 return err; 770 return err;
672} 771}
673 772
674size_t thread_stack__depth(struct thread *thread) 773size_t thread_stack__depth(struct thread *thread, int cpu)
675{ 774{
676 if (!thread->ts) 775 struct thread_stack *ts = thread__stack(thread, cpu);
776
777 if (!ts)
677 return 0; 778 return 0;
678 return thread->ts->cnt; 779 return ts->cnt;
679} 780}
diff --git a/tools/perf/util/thread-stack.h b/tools/perf/util/thread-stack.h
index f97c00a8c251..1f626f4a1c40 100644
--- a/tools/perf/util/thread-stack.h
+++ b/tools/perf/util/thread-stack.h
@@ -80,14 +80,14 @@ struct call_return_processor {
80 void *data; 80 void *data;
81}; 81};
82 82
83int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip, 83int thread_stack__event(struct thread *thread, int cpu, u32 flags, u64 from_ip,
84 u64 to_ip, u16 insn_len, u64 trace_nr); 84 u64 to_ip, u16 insn_len, u64 trace_nr);
85void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr); 85void thread_stack__set_trace_nr(struct thread *thread, int cpu, u64 trace_nr);
86void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, 86void thread_stack__sample(struct thread *thread, int cpu, struct ip_callchain *chain,
87 size_t sz, u64 ip, u64 kernel_start); 87 size_t sz, u64 ip, u64 kernel_start);
88int thread_stack__flush(struct thread *thread); 88int thread_stack__flush(struct thread *thread);
89void thread_stack__free(struct thread *thread); 89void thread_stack__free(struct thread *thread);
90size_t thread_stack__depth(struct thread *thread); 90size_t thread_stack__depth(struct thread *thread, int cpu);
91 91
92struct call_return_processor * 92struct call_return_processor *
93call_return_processor__new(int (*process)(struct call_return *cr, void *data), 93call_return_processor__new(int (*process)(struct call_return *cr, void *data),
diff --git a/tools/power/x86/turbostat/Makefile b/tools/power/x86/turbostat/Makefile
index 2ab25aa38263..1598b4fa0b11 100644
--- a/tools/power/x86/turbostat/Makefile
+++ b/tools/power/x86/turbostat/Makefile
@@ -9,13 +9,13 @@ ifeq ("$(origin O)", "command line")
9endif 9endif
10 10
11turbostat : turbostat.c 11turbostat : turbostat.c
12CFLAGS += -Wall 12override CFLAGS += -Wall
13CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"' 13override CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"'
14CFLAGS += -DINTEL_FAMILY_HEADER='"../../../../arch/x86/include/asm/intel-family.h"' 14override CFLAGS += -DINTEL_FAMILY_HEADER='"../../../../arch/x86/include/asm/intel-family.h"'
15 15
16%: %.c 16%: %.c
17 @mkdir -p $(BUILD_OUTPUT) 17 @mkdir -p $(BUILD_OUTPUT)
18 $(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@ 18 $(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@ $(LDFLAGS)
19 19
20.PHONY : clean 20.PHONY : clean
21clean : 21clean :
diff --git a/tools/power/x86/x86_energy_perf_policy/Makefile b/tools/power/x86/x86_energy_perf_policy/Makefile
index f4534fb8b951..ae7a0e09b722 100644
--- a/tools/power/x86/x86_energy_perf_policy/Makefile
+++ b/tools/power/x86/x86_energy_perf_policy/Makefile
@@ -9,12 +9,12 @@ ifeq ("$(origin O)", "command line")
9endif 9endif
10 10
11x86_energy_perf_policy : x86_energy_perf_policy.c 11x86_energy_perf_policy : x86_energy_perf_policy.c
12CFLAGS += -Wall 12override CFLAGS += -Wall
13CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"' 13override CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"'
14 14
15%: %.c 15%: %.c
16 @mkdir -p $(BUILD_OUTPUT) 16 @mkdir -p $(BUILD_OUTPUT)
17 $(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@ 17 $(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@ $(LDFLAGS)
18 18
19.PHONY : clean 19.PHONY : clean
20clean : 20clean :
diff --git a/tools/thermal/tmon/Makefile b/tools/thermal/tmon/Makefile
index 735a510230c3..89a2444c1df2 100644
--- a/tools/thermal/tmon/Makefile
+++ b/tools/thermal/tmon/Makefile
@@ -6,13 +6,13 @@ VERSION = 1.0
6 6
7BINDIR=usr/bin 7BINDIR=usr/bin
8WARNFLAGS=-Wall -Wshadow -W -Wformat -Wimplicit-function-declaration -Wimplicit-int 8WARNFLAGS=-Wall -Wshadow -W -Wformat -Wimplicit-function-declaration -Wimplicit-int
9CFLAGS+= -O1 ${WARNFLAGS} 9override CFLAGS+= -O1 ${WARNFLAGS}
10# Add "-fstack-protector" only if toolchain supports it. 10# Add "-fstack-protector" only if toolchain supports it.
11CFLAGS+= $(call cc-option,-fstack-protector) 11override CFLAGS+= $(call cc-option,-fstack-protector-strong)
12CC?= $(CROSS_COMPILE)gcc 12CC?= $(CROSS_COMPILE)gcc
13PKG_CONFIG?= pkg-config 13PKG_CONFIG?= pkg-config
14 14
15CFLAGS+=-D VERSION=\"$(VERSION)\" 15override CFLAGS+=-D VERSION=\"$(VERSION)\"
16LDFLAGS+= 16LDFLAGS+=
17TARGET=tmon 17TARGET=tmon
18 18
@@ -29,7 +29,7 @@ TMON_LIBS += $(shell $(PKG_CONFIG) --libs $(STATIC) panelw ncursesw 2> /dev/null
29 $(PKG_CONFIG) --libs $(STATIC) panel ncurses 2> /dev/null || \ 29 $(PKG_CONFIG) --libs $(STATIC) panel ncurses 2> /dev/null || \
30 echo -lpanel -lncurses) 30 echo -lpanel -lncurses)
31 31
32CFLAGS += $(shell $(PKG_CONFIG) --cflags $(STATIC) panelw ncursesw 2> /dev/null || \ 32override CFLAGS += $(shell $(PKG_CONFIG) --cflags $(STATIC) panelw ncursesw 2> /dev/null || \
33 $(PKG_CONFIG) --cflags $(STATIC) panel ncurses 2> /dev/null) 33 $(PKG_CONFIG) --cflags $(STATIC) panel ncurses 2> /dev/null)
34 34
35OBJS = tmon.o tui.o sysfs.o pid.o 35OBJS = tmon.o tui.o sysfs.o pid.o