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

Configure Feed

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

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

Pull perf tooling updates form Ingo Molnar:
"A final batch of perf tooling changes: mostly fixes and small
improvements"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (29 commits)
perf session: Add comment for perf_session__register_idle_thread()
perf thread-stack: Fix thread stack processing for the idle task
perf thread-stack: Allocate an array of thread stacks
perf thread-stack: Factor out thread_stack__init()
perf thread-stack: Allow for a thread stack array
perf thread-stack: Avoid direct reference to the thread's stack
perf thread-stack: Tidy thread_stack__bottom() usage
perf thread-stack: Simplify some code in thread_stack__process()
tools gpio: Allow overriding CFLAGS
tools power turbostat: Override CFLAGS assignments and add LDFLAGS to build command
tools thermal tmon: Allow overriding CFLAGS assignments
tools power x86_energy_perf_policy: Override CFLAGS assignments and add LDFLAGS to build command
perf c2c: Increase the HITM ratio limit for displayed cachelines
perf c2c: Change the default coalesce setup
perf trace beauty ioctl: Beautify USBDEVFS_ commands
perf trace beauty: Export function to get the files for a thread
perf trace: Wire up ioctl's USBDEBFS_ cmd table generator
perf beauty ioctl: Add generator for USBDEVFS_ ioctl commands
tools headers uapi: Grab a copy of usbdevice_fs.h
perf trace: Store the major number for a file when storing its pathname
...

+623 -169
+2 -2
tools/build/Makefile.feature
··· 82 82 cplus-demangle \ 83 83 hello \ 84 84 libbabeltrace \ 85 - liberty \ 86 - liberty-z \ 85 + libbfd-liberty \ 86 + libbfd-liberty-z \ 87 87 libunwind-debug-frame \ 88 88 libunwind-debug-frame-arm \ 89 89 libunwind-debug-frame-aarch64 \
+5 -5
tools/build/feature/Makefile
··· 17 17 test-libbfd.bin \ 18 18 test-disassembler-four-args.bin \ 19 19 test-reallocarray.bin \ 20 - test-liberty.bin \ 21 - test-liberty-z.bin \ 20 + test-libbfd-liberty.bin \ 21 + test-libbfd-liberty-z.bin \ 22 22 test-cplus-demangle.bin \ 23 23 test-libelf.bin \ 24 24 test-libelf-getphdrnum.bin \ ··· 210 210 $(BUILD) 211 211 212 212 $(OUTPUT)test-libbfd.bin: 213 - $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl 213 + $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl 214 214 215 215 $(OUTPUT)test-disassembler-four-args.bin: 216 216 $(BUILD) -DPACKAGE='"perf"' -lbfd -lopcodes ··· 218 218 $(OUTPUT)test-reallocarray.bin: 219 219 $(BUILD) 220 220 221 - $(OUTPUT)test-liberty.bin: 221 + $(OUTPUT)test-libbfd-liberty.bin: 222 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 225 $(CC) $(CFLAGS) -Wall -Werror -o $@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty -lz 226 226 227 227 $(OUTPUT)test-cplus-demangle.bin:
+1 -1
tools/gpio/Makefile
··· 12 12 # (this improves performance and avoids hard-to-debug behaviour); 13 13 MAKEFLAGS += -r 14 14 15 - CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include 15 + override CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include 16 16 17 17 ALL_TARGETS := lsgpio gpio-hammer gpio-event-mon 18 18 ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS))
+201
tools/include/uapi/linux/usbdevice_fs.h
··· 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 + 40 + struct 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 + 50 + struct usbdevfs_bulktransfer { 51 + unsigned int ep; 52 + unsigned int len; 53 + unsigned int timeout; /* in milliseconds */ 54 + void __user *data; 55 + }; 56 + 57 + struct usbdevfs_setinterface { 58 + unsigned int interface; 59 + unsigned int altsetting; 60 + }; 61 + 62 + struct usbdevfs_disconnectsignal { 63 + unsigned int signr; 64 + void __user *context; 65 + }; 66 + 67 + #define USBDEVFS_MAXDRIVERNAME 255 68 + 69 + struct usbdevfs_getdriver { 70 + unsigned int interface; 71 + char driver[USBDEVFS_MAXDRIVERNAME + 1]; 72 + }; 73 + 74 + struct 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 + 91 + struct usbdevfs_iso_packet_desc { 92 + unsigned int length; 93 + unsigned int actual_length; 94 + unsigned int status; 95 + }; 96 + 97 + struct 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 */ 118 + struct 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. */ 127 + struct 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 + 148 + struct usbdevfs_disconnect_claim { 149 + unsigned int interface; 150 + unsigned int flags; 151 + char driver[USBDEVFS_MAXDRIVERNAME + 1]; 152 + }; 153 + 154 + struct 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 */
+23 -21
tools/perf/Makefile.config
··· 702 702 703 703 ifeq ($(feature-libbfd), 1) 704 704 EXTLIBS += -lbfd 705 + else 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 709 # call all detections now so we get correct 707 710 # status in VF output 708 - $(call feature_check,liberty) 709 - $(call feature_check,liberty-z) 710 - $(call feature_check,cplus-demangle) 711 + $(call feature_check,libbfd-liberty) 712 + $(call feature_check,libbfd-liberty-z) 711 713 712 - ifeq ($(feature-liberty), 1) 713 - EXTLIBS += -liberty 714 + ifeq ($(feature-libbfd-liberty), 1) 715 + EXTLIBS += -lbfd -liberty 714 716 else 715 - ifeq ($(feature-liberty-z), 1) 716 - EXTLIBS += -liberty -lz 717 + ifeq ($(feature-libbfd-liberty-z), 1) 718 + EXTLIBS += -lbfd -liberty -lz 717 719 endif 718 720 endif 719 721 endif ··· 725 723 else 726 724 ifdef HAVE_CPLUS_DEMANGLE_SUPPORT 727 725 EXTLIBS += -liberty 728 - CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT 729 726 else 730 - ifneq ($(feature-libbfd), 1) 731 - ifneq ($(feature-liberty), 1) 732 - ifneq ($(feature-liberty-z), 1) 733 - # we dont have neither HAVE_CPLUS_DEMANGLE_SUPPORT 734 - # or any of 'bfd iberty z' trinity 735 - ifeq ($(feature-cplus-demangle), 1) 736 - EXTLIBS += -liberty 737 - CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT 738 - else 739 - msg := $(warning No bfd.h/libbfd found, please install binutils-dev[el]/zlib-static/libiberty-dev to gain symbol demangling) 740 - CFLAGS += -DNO_DEMANGLE 741 - endif 742 - endif 727 + ifeq ($(filter -liberty,$(EXTLIBS)),) 728 + $(call feature_check,cplus-demangle) 729 + 730 + # we dont have neither HAVE_CPLUS_DEMANGLE_SUPPORT 731 + # or any of 'bfd iberty z' trinity 732 + ifeq ($(feature-cplus-demangle), 1) 733 + EXTLIBS += -liberty 734 + else 735 + msg := $(warning No bfd.h/libbfd found, please install binutils-dev[el]/zlib-static/libiberty-dev to gain symbol demangling) 736 + CFLAGS += -DNO_DEMANGLE 743 737 endif 744 738 endif 739 + endif 740 + 741 + ifneq ($(filter -liberty,$(EXTLIBS)),) 742 + CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT 745 743 endif 746 744 endif 747 745
+8
tools/perf/Makefile.perf
··· 497 497 $(prctl_option_array): $(prctl_hdr_dir)/prctl.h $(prctl_option_tbl) 498 498 $(Q)$(SHELL) '$(prctl_option_tbl)' $(prctl_hdr_dir) > $@ 499 499 500 + usbdevfs_ioctl_array := $(beauty_ioctl_outdir)/usbdevfs_ioctl_array.c 501 + usbdevfs_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 + 500 506 x86_arch_prctl_code_array := $(beauty_outdir)/x86_arch_prctl_code_array.c 501 507 x86_arch_prctl_code_tbl := $(srctree)/tools/perf/trace/beauty/x86_arch_prctl.sh 502 508 ··· 630 624 $(mount_flags_array) \ 631 625 $(perf_ioctl_array) \ 632 626 $(prctl_option_array) \ 627 + $(usbdevfs_ioctl_array) \ 633 628 $(x86_arch_prctl_code_array) \ 634 629 $(rename_flags_array) \ 635 630 $(arch_errno_name_array) ··· 930 923 $(OUTPUT)$(vhost_virtio_ioctl_array) \ 931 924 $(OUTPUT)$(perf_ioctl_array) \ 932 925 $(OUTPUT)$(prctl_option_array) \ 926 + $(OUTPUT)$(usbdevfs_ioctl_array) \ 933 927 $(OUTPUT)$(x86_arch_prctl_code_array) \ 934 928 $(OUTPUT)$(rename_flags_array) \ 935 929 $(OUTPUT)$(arch_errno_name_array)
+2 -2
tools/perf/builtin-c2c.c
··· 68 68 struct hist_entry he; 69 69 }; 70 70 71 - static char const *coalesce_default = "pid,iaddr"; 71 + static char const *coalesce_default = "iaddr"; 72 72 73 73 struct perf_c2c { 74 74 struct perf_tool tool; ··· 1878 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 1883 1883 static bool he__display(struct hist_entry *he, struct c2c_stats *stats) 1884 1884 {
+18 -3
tools/perf/builtin-script.c
··· 1073 1073 1074 1074 /* 1075 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 1082 start = br->entries[0].to; 1078 1083 end = sample->ip; 1084 + if (end < start) { 1085 + /* Missing jump. Scan 128 bytes for the next branch */ 1086 + end = start + 128; 1087 + } 1079 1088 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, true); 1080 1089 printed += ip__fprintf_sym(start, thread, x.cpumode, x.cpu, &lastsym, attr, fp); 1081 1090 if (len <= 0) { ··· 1093 1084 machine, thread, &x.is64bit, &x.cpumode, false); 1094 1085 if (len <= 0) 1095 1086 goto out; 1096 - 1097 1087 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", sample->ip, 1098 1088 dump_insn(&x, sample->ip, buffer, len, NULL)); 1099 1089 if (PRINT_FIELD(SRCCODE)) ··· 1104 1096 dump_insn(&x, start + off, buffer + off, len - off, &ilen)); 1105 1097 if (ilen == 0) 1106 1098 break; 1099 + if (arch_is_branch(buffer + off, len - off, x.is64bit) && start + off != sample->ip) { 1100 + /* 1101 + * Hit a missing branch. Just stop. 1102 + */ 1103 + printed += fprintf(fp, "\t... not reaching sample ...\n"); 1104 + break; 1105 + } 1107 1106 if (PRINT_FIELD(SRCCODE)) 1108 1107 print_srccode(thread, x.cpumode, start + off); 1109 1108 } ··· 1182 1167 struct addr_location *al, FILE *fp) 1183 1168 { 1184 1169 struct perf_event_attr *attr = &evsel->attr; 1185 - size_t depth = thread_stack__depth(thread); 1170 + size_t depth = thread_stack__depth(thread, sample->cpu); 1186 1171 const char *name = NULL; 1187 1172 static int spacing; 1188 1173 int len = 0; ··· 1716 1701 struct thread *thread, 1717 1702 struct addr_location *al) 1718 1703 { 1719 - int depth = thread_stack__depth(thread); 1704 + int depth = thread_stack__depth(thread, sample->cpu); 1720 1705 1721 1706 if (!symbol_conf.graph_function) 1722 1707 return true;
+100 -48
tools/perf/builtin-trace.c
··· 60 60 #include <linux/stringify.h> 61 61 #include <linux/time64.h> 62 62 #include <fcntl.h> 63 + #include <sys/sysmacros.h> 63 64 64 65 #include "sane_ctype.h" 65 66 ··· 113 112 } stats; 114 113 unsigned int max_stack; 115 114 unsigned int min_stack; 116 - bool sort_events; 115 + int raw_augmented_syscalls_args_size; 117 116 bool raw_augmented_syscalls; 117 + bool sort_events; 118 118 bool not_ev_qualifier; 119 119 bool live; 120 120 bool full_time; ··· 285 283 return -ENOENT; 286 284 } 287 285 288 - static int perf_evsel__init_augmented_syscall_tp(struct perf_evsel *evsel) 286 + static int perf_evsel__init_augmented_syscall_tp(struct perf_evsel *evsel, struct perf_evsel *tp) 289 287 { 290 288 struct syscall_tp *sc = evsel->priv = malloc(sizeof(struct syscall_tp)); 291 289 292 - if (evsel->priv != NULL) { /* field, sizeof_field, offsetof_field */ 293 - if (__tp_field__init_uint(&sc->id, sizeof(long), sizeof(long long), evsel->needs_swap)) 290 + if (evsel->priv != NULL) { 291 + struct tep_format_field *syscall_id = perf_evsel__field(tp, "id"); 292 + if (syscall_id == NULL) 293 + syscall_id = perf_evsel__field(tp, "__syscall_nr"); 294 + if (syscall_id == NULL) 295 + goto out_delete; 296 + if (__tp_field__init_uint(&sc->id, syscall_id->size, syscall_id->offset, evsel->needs_swap)) 294 297 goto out_delete; 295 298 296 299 return 0; ··· 981 974 char *name; 982 975 } filename; 983 976 struct { 984 - int max; 985 - char **table; 986 - } paths; 977 + int max; 978 + struct file *table; 979 + } files; 987 980 988 981 struct intlist *syscall_stats; 989 982 }; ··· 993 986 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace)); 994 987 995 988 if (ttrace) 996 - ttrace->paths.max = -1; 989 + ttrace->files.max = -1; 997 990 998 991 ttrace->syscall_stats = intlist__new(NULL); 999 992 ··· 1037 1030 1038 1031 static const size_t trace__entry_str_size = 2048; 1039 1032 1033 + static struct file *thread_trace__files_entry(struct thread_trace *ttrace, int fd) 1034 + { 1035 + if (fd > ttrace->files.max) { 1036 + struct file *nfiles = realloc(ttrace->files.table, (fd + 1) * sizeof(struct file)); 1037 + 1038 + if (nfiles == NULL) 1039 + return NULL; 1040 + 1041 + if (ttrace->files.max != -1) { 1042 + memset(nfiles + ttrace->files.max + 1, 0, 1043 + (fd - ttrace->files.max) * sizeof(struct file)); 1044 + } else { 1045 + memset(nfiles, 0, (fd + 1) * sizeof(struct file)); 1046 + } 1047 + 1048 + ttrace->files.table = nfiles; 1049 + ttrace->files.max = fd; 1050 + } 1051 + 1052 + return ttrace->files.table + fd; 1053 + } 1054 + 1055 + struct file *thread__files_entry(struct thread *thread, int fd) 1056 + { 1057 + return thread_trace__files_entry(thread__priv(thread), fd); 1058 + } 1059 + 1040 1060 static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname) 1041 1061 { 1042 1062 struct thread_trace *ttrace = thread__priv(thread); 1063 + struct file *file = thread_trace__files_entry(ttrace, fd); 1043 1064 1044 - if (fd > ttrace->paths.max) { 1045 - char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *)); 1046 - 1047 - if (npath == NULL) 1048 - return -1; 1049 - 1050 - if (ttrace->paths.max != -1) { 1051 - memset(npath + ttrace->paths.max + 1, 0, 1052 - (fd - ttrace->paths.max) * sizeof(char *)); 1053 - } else { 1054 - memset(npath, 0, (fd + 1) * sizeof(char *)); 1055 - } 1056 - 1057 - ttrace->paths.table = npath; 1058 - ttrace->paths.max = fd; 1065 + if (file != NULL) { 1066 + struct stat st; 1067 + if (stat(pathname, &st) == 0) 1068 + file->dev_maj = major(st.st_rdev); 1069 + file->pathname = strdup(pathname); 1070 + if (file->pathname) 1071 + return 0; 1059 1072 } 1060 1073 1061 - ttrace->paths.table[fd] = strdup(pathname); 1062 - 1063 - return ttrace->paths.table[fd] != NULL ? 0 : -1; 1074 + return -1; 1064 1075 } 1065 1076 1066 1077 static int thread__read_fd_path(struct thread *thread, int fd) ··· 1118 1093 if (fd < 0) 1119 1094 return NULL; 1120 1095 1121 - if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL)) { 1096 + if ((fd > ttrace->files.max || ttrace->files.table[fd].pathname == NULL)) { 1122 1097 if (!trace->live) 1123 1098 return NULL; 1124 1099 ++trace->stats.proc_getname; ··· 1126 1101 return NULL; 1127 1102 } 1128 1103 1129 - return ttrace->paths.table[fd]; 1104 + return ttrace->files.table[fd].pathname; 1130 1105 } 1131 1106 1132 1107 size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg) ··· 1165 1140 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg); 1166 1141 struct thread_trace *ttrace = thread__priv(arg->thread); 1167 1142 1168 - if (ttrace && fd >= 0 && fd <= ttrace->paths.max) 1169 - zfree(&ttrace->paths.table[fd]); 1143 + if (ttrace && fd >= 0 && fd <= ttrace->files.max) 1144 + zfree(&ttrace->files.table[fd].pathname); 1170 1145 1171 1146 return printed; 1172 1147 } ··· 1793 1768 return printed; 1794 1769 } 1795 1770 1796 - static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sample, int *augmented_args_size, bool raw_augmented) 1771 + static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sample, int *augmented_args_size, int raw_augmented_args_size) 1797 1772 { 1798 1773 void *augmented_args = NULL; 1799 1774 /* 1800 1775 * For now with BPF raw_augmented we hook into raw_syscalls:sys_enter 1801 - * and there we get all 6 syscall args plus the tracepoint common 1802 - * fields (sizeof(long)) and the syscall_nr (another long). So we check 1803 - * if that is the case and if so don't look after the sc->args_size, 1804 - * but always after the full raw_syscalls:sys_enter payload, which is 1805 - * fixed. 1776 + * and there we get all 6 syscall args plus the tracepoint common fields 1777 + * that gets calculated at the start and the syscall_nr (another long). 1778 + * So we check if that is the case and if so don't look after the 1779 + * sc->args_size but always after the full raw_syscalls:sys_enter payload, 1780 + * which is fixed. 1806 1781 * 1807 1782 * We'll revisit this later to pass s->args_size to the BPF augmenter 1808 1783 * (now tools/perf/examples/bpf/augmented_raw_syscalls.c, so that it ··· 1810 1785 * use syscalls:sys_enter_NAME, so that we reduce the kernel/userspace 1811 1786 * traffic to just what is needed for each syscall. 1812 1787 */ 1813 - int args_size = raw_augmented ? (8 * (int)sizeof(long)) : sc->args_size; 1788 + int args_size = raw_augmented_args_size ?: sc->args_size; 1814 1789 1815 1790 *augmented_args_size = sample->raw_size - args_size; 1816 1791 if (*augmented_args_size > 0) ··· 1864 1839 * here and avoid using augmented syscalls when the evsel is the raw_syscalls one. 1865 1840 */ 1866 1841 if (evsel != trace->syscalls.events.sys_enter) 1867 - augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size, trace->raw_augmented_syscalls); 1842 + augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size, trace->raw_augmented_syscalls_args_size); 1868 1843 ttrace->entry_time = sample->time; 1869 1844 msg = ttrace->entry_str; 1870 1845 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name); ··· 1922 1897 goto out_put; 1923 1898 1924 1899 args = perf_evsel__sc_tp_ptr(evsel, args, sample); 1925 - augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size, trace->raw_augmented_syscalls); 1900 + augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size, trace->raw_augmented_syscalls_args_size); 1926 1901 syscall__scnprintf_args(sc, msg, sizeof(msg), args, augmented_args, augmented_args_size, trace, thread); 1927 1902 fprintf(trace->output, "%s", msg); 1928 1903 err = 0; ··· 2711 2686 { 2712 2687 if (trace->syscalls.map) 2713 2688 return trace__set_ev_qualifier_bpf_filter(trace); 2714 - return trace__set_ev_qualifier_tp_filter(trace); 2689 + if (trace->syscalls.events.sys_enter) 2690 + return trace__set_ev_qualifier_tp_filter(trace); 2691 + return 0; 2715 2692 } 2716 2693 2717 2694 static int bpf_map__set_filter_pids(struct bpf_map *map __maybe_unused, ··· 3839 3812 * syscall. 3840 3813 */ 3841 3814 if (trace.syscalls.events.augmented) { 3842 - evsel = trace.syscalls.events.augmented; 3843 - 3844 - if (perf_evsel__init_augmented_syscall_tp(evsel) || 3845 - perf_evsel__init_augmented_syscall_tp_args(evsel)) 3846 - goto out; 3847 - evsel->handler = trace__sys_enter; 3848 - 3849 3815 evlist__for_each_entry(trace.evlist, evsel) { 3850 3816 bool raw_syscalls_sys_exit = strcmp(perf_evsel__name(evsel), "raw_syscalls:sys_exit") == 0; 3851 3817 ··· 3847 3827 goto init_augmented_syscall_tp; 3848 3828 } 3849 3829 3830 + if (strcmp(perf_evsel__name(evsel), "raw_syscalls:sys_enter") == 0) { 3831 + struct perf_evsel *augmented = trace.syscalls.events.augmented; 3832 + if (perf_evsel__init_augmented_syscall_tp(augmented, evsel) || 3833 + perf_evsel__init_augmented_syscall_tp_args(augmented)) 3834 + goto out; 3835 + augmented->handler = trace__sys_enter; 3836 + } 3837 + 3850 3838 if (strstarts(perf_evsel__name(evsel), "syscalls:sys_exit_")) { 3839 + struct syscall_tp *sc; 3851 3840 init_augmented_syscall_tp: 3852 - perf_evsel__init_augmented_syscall_tp(evsel); 3841 + if (perf_evsel__init_augmented_syscall_tp(evsel, evsel)) 3842 + goto out; 3843 + sc = evsel->priv; 3844 + /* 3845 + * For now with BPF raw_augmented we hook into 3846 + * raw_syscalls:sys_enter and there we get all 3847 + * 6 syscall args plus the tracepoint common 3848 + * fields and the syscall_nr (another long). 3849 + * So we check if that is the case and if so 3850 + * don't look after the sc->args_size but 3851 + * always after the full raw_syscalls:sys_enter 3852 + * payload, which is fixed. 3853 + * 3854 + * We'll revisit this later to pass 3855 + * s->args_size to the BPF augmenter (now 3856 + * tools/perf/examples/bpf/augmented_raw_syscalls.c, 3857 + * so that it copies only what we need for each 3858 + * syscall, like what happens when we use 3859 + * syscalls:sys_enter_NAME, so that we reduce 3860 + * the kernel/userspace traffic to just what is 3861 + * needed for each syscall. 3862 + */ 3863 + if (trace.raw_augmented_syscalls) 3864 + trace.raw_augmented_syscalls_args_size = (6 + 1) * sizeof(long) + sc->id.offset; 3853 3865 perf_evsel__init_augmented_syscall_tp_ret(evsel); 3854 3866 evsel->handler = trace__sys_exit; 3855 3867 }
+1
tools/perf/check-headers.sh
··· 14 14 include/uapi/linux/prctl.h 15 15 include/uapi/linux/sched.h 16 16 include/uapi/linux/stat.h 17 + include/uapi/linux/usbdevice_fs.h 17 18 include/uapi/linux/vhost.h 18 19 include/uapi/sound/asound.h 19 20 include/linux/bits.h
+7
tools/perf/trace/beauty/beauty.h
··· 32 32 struct trace; 33 33 struct thread; 34 34 35 + struct file { 36 + char *pathname; 37 + int dev_maj; 38 + }; 39 + 40 + struct file *thread__files_entry(struct thread *thread, int fd); 41 + 35 42 struct strarrays { 36 43 int nr_entries; 37 44 struct strarray **entries;
+22
tools/perf/trace/beauty/ioctl.c
··· 112 112 return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAE, nr, dir); 113 113 } 114 114 115 + static 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 + 115 126 static size_t ioctl__scnprintf_cmd(unsigned long cmd, char *bf, size_t size, bool show_prefix) 116 127 { 117 128 const char *prefix = "_IOC_"; ··· 168 157 return printed + scnprintf(bf + printed, size - printed, ", %#x, %#x, %#x)", type, nr, sz); 169 158 } 170 159 160 + #ifndef USB_DEVICE_MAJOR 161 + #define USB_DEVICE_MAJOR 189 162 + #endif // USB_DEVICE_MAJOR 163 + 171 164 size_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_arg *arg) 172 165 { 173 166 unsigned long cmd = arg->val; 167 + unsigned int fd = syscall_arg__val(arg, 0); 168 + struct file *file = thread__files_entry(arg->thread, fd); 169 + 170 + if (file != NULL) { 171 + if (file->dev_maj == USB_DEVICE_MAJOR) 172 + return ioctl__scnprintf_usbdevfs_cmd(_IOC_NR(cmd), _IOC_DIR(cmd), bf, size); 173 + } 174 174 175 175 return ioctl__scnprintf_cmd(cmd, bf, size, arg->show_string_prefix); 176 176 }
+1 -1
tools/perf/trace/beauty/mmap.c
··· 18 18 } 19 19 20 20 P_MMAP_PROT(READ); 21 - P_MMAP_PROT(EXEC); 22 21 P_MMAP_PROT(WRITE); 22 + P_MMAP_PROT(EXEC); 23 23 P_MMAP_PROT(SEM); 24 24 P_MMAP_PROT(GROWSDOWN); 25 25 P_MMAP_PROT(GROWSUP);
+2 -2
tools/perf/trace/beauty/seccomp.c
··· 9 9 static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg) 10 10 { 11 11 bool show_prefix = arg->show_string_prefix; 12 - const char *prefix = "SECOMP_SET_MODE_"; 12 + const char *prefix = "SECCOMP_SET_MODE_"; 13 13 int op = arg->val; 14 14 size_t printed = 0; 15 15 ··· 34 34 struct syscall_arg *arg) 35 35 { 36 36 bool show_prefix = arg->show_string_prefix; 37 - const char *prefix = "SECOMP_FILTER_FLAG_"; 37 + const char *prefix = "SECCOMP_FILTER_FLAG_"; 38 38 int printed = 0, flags = arg->val; 39 39 40 40 #define P_FLAG(n) \
+19
tools/perf/trace/beauty/usbdevfs_ioctl.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: LGPL-2.1 3 + 4 + [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ 5 + 6 + printf "static const char *usbdevfs_ioctl_cmds[] = {\n" 7 + regex="^#[[:space:]]*define[[:space:]]+USBDEVFS_(\w+)[[:space:]]+_IO[WR]{0,2}\([[:space:]]*'U'[[:space:]]*,[[:space:]]*([[:digit:]]+).*" 8 + egrep $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" 11 + printf "};\n\n" 12 + printf "#if 0\n" 13 + printf "static const char *usbdevfs_ioctl_32_cmds[] = {\n" 14 + regex="^#[[:space:]]*define[[:space:]]+USBDEVFS_(\w+)[[:space:]]+_IO[WR]{0,2}\([[:space:]]*'U'[[:space:]]*,[[:space:]]*([[:digit:]]+).*" 15 + egrep $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" 18 + printf "};\n" 19 + printf "#endif\n"
+8
tools/perf/util/dump-insn.c
··· 13 13 *lenp = 0; 14 14 return "?"; 15 15 } 16 + 17 + __weak 18 + int 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 + }
+2
tools/perf/util/dump-insn.h
··· 20 20 21 21 const char *dump_insn(struct perf_insn *x, u64 ip, 22 22 u8 *inbuf, int inlen, int *lenp); 23 + int arch_is_branch(const unsigned char *buf, size_t len, int x86_64); 24 + 23 25 #endif
+2 -2
tools/perf/util/intel-bts.c
··· 451 451 continue; 452 452 intel_bts_get_branch_type(btsq, branch); 453 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 455 le64_to_cpu(branch->from), 456 456 le64_to_cpu(branch->to), 457 457 btsq->intel_pt_insn.length, ··· 523 523 !btsq->bts->synth_opts.thread_stack && thread && 524 524 (!old_buffer || btsq->bts->sampling_mode || 525 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 528 err = intel_bts_process_buffer(btsq, buffer, thread); 529 529
+8
tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
··· 180 180 return 0; 181 181 } 182 182 183 + int 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 + 183 191 const char *dump_insn(struct perf_insn *x, uint64_t ip __maybe_unused, 184 192 u8 *inbuf, int inlen, int *lenp) 185 193 {
+3 -3
tools/perf/util/intel-pt.c
··· 1174 1174 intel_pt_prep_b_sample(pt, ptq, event, sample); 1175 1175 1176 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 1178 pt->synth_opts.callchain_sz + 1, 1179 1179 sample->ip, pt->kernel_start); 1180 1180 sample->callchain = ptq->chain; ··· 1526 1526 return 0; 1527 1527 1528 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 1530 state->to_ip, ptq->insn_len, 1531 1531 state->trace_nr); 1532 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 1535 if (pt->sample_branches) { 1536 1536 err = intel_pt_synth_branch_sample(ptq);
+2 -1
tools/perf/util/python.c
··· 939 939 940 940 file = PyFile_FromFile(fp, "perf", "r", NULL); 941 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 944 #endif 944 945 if (file == NULL) 945 946 goto free_list;
+7
tools/perf/util/session.c
··· 1527 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 + */ 1530 1537 int perf_session__register_idle_thread(struct perf_session *session) 1531 1538 { 1532 1539 struct thread *thread;
+164 -63
tools/perf/util/thread-stack.c
··· 15 15 16 16 #include <linux/rbtree.h> 17 17 #include <linux/list.h> 18 + #include <linux/log2.h> 18 19 #include <errno.h> 19 20 #include "thread.h" 20 21 #include "event.h" ··· 61 60 * @last_time: last timestamp 62 61 * @crp: call/return processor 63 62 * @comm: current comm 63 + * @arr_sz: size of array if this is the first element of an array 64 64 */ 65 65 struct thread_stack { 66 66 struct thread_stack_entry *stack; ··· 73 71 u64 last_time; 74 72 struct call_return_processor *crp; 75 73 struct comm *comm; 74 + unsigned int arr_sz; 76 75 }; 76 + 77 + /* 78 + * Assume pid == tid == 0 identifies the idle task as defined by 79 + * perf_session__register_idle_thread(). The idle task is really 1 task per cpu, 80 + * and therefore requires a stack for each cpu. 81 + */ 82 + static inline bool thread_stack__per_cpu(struct thread *thread) 83 + { 84 + return !(thread->tid || thread->pid_); 85 + } 77 86 78 87 static int thread_stack__grow(struct thread_stack *ts) 79 88 { ··· 104 91 return 0; 105 92 } 106 93 107 - static struct thread_stack *thread_stack__new(struct thread *thread, 108 - struct call_return_processor *crp) 94 + static int thread_stack__init(struct thread_stack *ts, struct thread *thread, 95 + struct call_return_processor *crp) 109 96 { 110 - struct thread_stack *ts; 97 + int err; 111 98 112 - ts = zalloc(sizeof(struct thread_stack)); 113 - if (!ts) 114 - return NULL; 115 - 116 - if (thread_stack__grow(ts)) { 117 - free(ts); 118 - return NULL; 119 - } 99 + err = thread_stack__grow(ts); 100 + if (err) 101 + return err; 120 102 121 103 if (thread->mg && thread->mg->machine) 122 104 ts->kernel_start = machine__kernel_start(thread->mg->machine); ··· 119 111 ts->kernel_start = 1ULL << 63; 120 112 ts->crp = crp; 121 113 114 + return 0; 115 + } 116 + 117 + static struct thread_stack *thread_stack__new(struct thread *thread, int cpu, 118 + struct call_return_processor *crp) 119 + { 120 + struct thread_stack *ts = thread->ts, *new_ts; 121 + unsigned int old_sz = ts ? ts->arr_sz : 0; 122 + unsigned int new_sz = 1; 123 + 124 + if (thread_stack__per_cpu(thread) && cpu > 0) 125 + new_sz = roundup_pow_of_two(cpu + 1); 126 + 127 + if (!ts || new_sz > old_sz) { 128 + new_ts = calloc(new_sz, sizeof(*ts)); 129 + if (!new_ts) 130 + return NULL; 131 + if (ts) 132 + memcpy(new_ts, ts, old_sz * sizeof(*ts)); 133 + new_ts->arr_sz = new_sz; 134 + zfree(&thread->ts); 135 + thread->ts = new_ts; 136 + ts = new_ts; 137 + } 138 + 139 + if (thread_stack__per_cpu(thread) && cpu > 0 && 140 + (unsigned int)cpu < ts->arr_sz) 141 + ts += cpu; 142 + 143 + if (!ts->stack && 144 + thread_stack__init(ts, thread, crp)) 145 + return NULL; 146 + 122 147 return ts; 148 + } 149 + 150 + static struct thread_stack *thread__cpu_stack(struct thread *thread, int cpu) 151 + { 152 + struct thread_stack *ts = thread->ts; 153 + 154 + if (cpu < 0) 155 + cpu = 0; 156 + 157 + if (!ts || (unsigned int)cpu >= ts->arr_sz) 158 + return NULL; 159 + 160 + ts += cpu; 161 + 162 + if (!ts->stack) 163 + return NULL; 164 + 165 + return ts; 166 + } 167 + 168 + static inline struct thread_stack *thread__stack(struct thread *thread, 169 + int cpu) 170 + { 171 + if (!thread) 172 + return NULL; 173 + 174 + if (thread_stack__per_cpu(thread)) 175 + return thread__cpu_stack(thread, cpu); 176 + 177 + return thread->ts; 123 178 } 124 179 125 180 static int thread_stack__push(struct thread_stack *ts, u64 ret_addr, ··· 297 226 298 227 int thread_stack__flush(struct thread *thread) 299 228 { 300 - if (thread->ts) 301 - return __thread_stack__flush(thread, thread->ts); 229 + struct thread_stack *ts = thread->ts; 230 + unsigned int pos; 231 + int err = 0; 302 232 303 - return 0; 233 + if (ts) { 234 + for (pos = 0; pos < ts->arr_sz; pos++) { 235 + int ret = __thread_stack__flush(thread, ts + pos); 236 + 237 + if (ret) 238 + err = ret; 239 + } 240 + } 241 + 242 + return err; 304 243 } 305 244 306 - int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip, 245 + int thread_stack__event(struct thread *thread, int cpu, u32 flags, u64 from_ip, 307 246 u64 to_ip, u16 insn_len, u64 trace_nr) 308 247 { 248 + struct thread_stack *ts = thread__stack(thread, cpu); 249 + 309 250 if (!thread) 310 251 return -EINVAL; 311 252 312 - if (!thread->ts) { 313 - thread->ts = thread_stack__new(thread, NULL); 314 - if (!thread->ts) { 253 + if (!ts) { 254 + ts = thread_stack__new(thread, cpu, NULL); 255 + if (!ts) { 315 256 pr_warning("Out of memory: no thread stack\n"); 316 257 return -ENOMEM; 317 258 } 318 - thread->ts->trace_nr = trace_nr; 259 + ts->trace_nr = trace_nr; 319 260 } 320 261 321 262 /* ··· 335 252 * the stack might be completely invalid. Better to report nothing than 336 253 * to report something misleading, so flush the stack. 337 254 */ 338 - if (trace_nr != thread->ts->trace_nr) { 339 - if (thread->ts->trace_nr) 340 - __thread_stack__flush(thread, thread->ts); 341 - thread->ts->trace_nr = trace_nr; 255 + if (trace_nr != ts->trace_nr) { 256 + if (ts->trace_nr) 257 + __thread_stack__flush(thread, ts); 258 + ts->trace_nr = trace_nr; 342 259 } 343 260 344 261 /* Stop here if thread_stack__process() is in use */ 345 - if (thread->ts->crp) 262 + if (ts->crp) 346 263 return 0; 347 264 348 265 if (flags & PERF_IP_FLAG_CALL) { ··· 353 270 ret_addr = from_ip + insn_len; 354 271 if (ret_addr == to_ip) 355 272 return 0; /* Zero-length calls are excluded */ 356 - return thread_stack__push(thread->ts, ret_addr, 273 + return thread_stack__push(ts, ret_addr, 357 274 flags & PERF_IP_FLAG_TRACE_END); 358 275 } else if (flags & PERF_IP_FLAG_TRACE_BEGIN) { 359 276 /* ··· 363 280 * address, so try to pop that. Also, do not expect a call made 364 281 * when the trace ended, to return, so pop that. 365 282 */ 366 - thread_stack__pop(thread->ts, to_ip); 367 - thread_stack__pop_trace_end(thread->ts); 283 + thread_stack__pop(ts, to_ip); 284 + thread_stack__pop_trace_end(ts); 368 285 } else if ((flags & PERF_IP_FLAG_RETURN) && from_ip) { 369 - thread_stack__pop(thread->ts, to_ip); 286 + thread_stack__pop(ts, to_ip); 370 287 } 371 288 372 289 return 0; 373 290 } 374 291 375 - void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr) 292 + void thread_stack__set_trace_nr(struct thread *thread, int cpu, u64 trace_nr) 376 293 { 377 - if (!thread || !thread->ts) 294 + struct thread_stack *ts = thread__stack(thread, cpu); 295 + 296 + if (!ts) 378 297 return; 379 298 380 - if (trace_nr != thread->ts->trace_nr) { 381 - if (thread->ts->trace_nr) 382 - __thread_stack__flush(thread, thread->ts); 383 - thread->ts->trace_nr = trace_nr; 299 + if (trace_nr != ts->trace_nr) { 300 + if (ts->trace_nr) 301 + __thread_stack__flush(thread, ts); 302 + ts->trace_nr = trace_nr; 384 303 } 304 + } 305 + 306 + static void __thread_stack__free(struct thread *thread, struct thread_stack *ts) 307 + { 308 + __thread_stack__flush(thread, ts); 309 + zfree(&ts->stack); 310 + } 311 + 312 + static void thread_stack__reset(struct thread *thread, struct thread_stack *ts) 313 + { 314 + unsigned int arr_sz = ts->arr_sz; 315 + 316 + __thread_stack__free(thread, ts); 317 + memset(ts, 0, sizeof(*ts)); 318 + ts->arr_sz = arr_sz; 385 319 } 386 320 387 321 void thread_stack__free(struct thread *thread) 388 322 { 389 - if (thread->ts) { 390 - __thread_stack__flush(thread, thread->ts); 391 - zfree(&thread->ts->stack); 323 + struct thread_stack *ts = thread->ts; 324 + unsigned int pos; 325 + 326 + if (ts) { 327 + for (pos = 0; pos < ts->arr_sz; pos++) 328 + __thread_stack__free(thread, ts + pos); 392 329 zfree(&thread->ts); 393 330 } 394 331 } ··· 418 315 return ip < kernel_start ? PERF_CONTEXT_USER : PERF_CONTEXT_KERNEL; 419 316 } 420 317 421 - void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, 318 + void thread_stack__sample(struct thread *thread, int cpu, 319 + struct ip_callchain *chain, 422 320 size_t sz, u64 ip, u64 kernel_start) 423 321 { 322 + struct thread_stack *ts = thread__stack(thread, cpu); 424 323 u64 context = callchain_context(ip, kernel_start); 425 324 u64 last_context; 426 325 size_t i, j; ··· 435 330 chain->ips[0] = context; 436 331 chain->ips[1] = ip; 437 332 438 - if (!thread || !thread->ts) { 333 + if (!ts) { 439 334 chain->nr = 2; 440 335 return; 441 336 } 442 337 443 338 last_context = context; 444 339 445 - for (i = 2, j = 1; i < sz && j <= thread->ts->cnt; i++, j++) { 446 - ip = thread->ts->stack[thread->ts->cnt - j].ret_addr; 340 + for (i = 2, j = 1; i < sz && j <= ts->cnt; i++, j++) { 341 + ip = ts->stack[ts->cnt - j].ret_addr; 447 342 context = callchain_context(ip, kernel_start); 448 343 if (context != last_context) { 449 344 if (i >= sz - 1) ··· 554 449 return 1; 555 450 } 556 451 557 - static int thread_stack__bottom(struct thread *thread, struct thread_stack *ts, 452 + static int thread_stack__bottom(struct thread_stack *ts, 558 453 struct perf_sample *sample, 559 454 struct addr_location *from_al, 560 455 struct addr_location *to_al, u64 ref) ··· 579 474 if (!cp) 580 475 return -ENOMEM; 581 476 582 - return thread_stack__push_cp(thread->ts, ip, sample->time, ref, cp, 477 + return thread_stack__push_cp(ts, ip, sample->time, ref, cp, 583 478 true, false); 584 479 } 585 480 ··· 695 590 struct addr_location *to_al, u64 ref, 696 591 struct call_return_processor *crp) 697 592 { 698 - struct thread_stack *ts = thread->ts; 593 + struct thread_stack *ts = thread__stack(thread, sample->cpu); 699 594 int err = 0; 700 595 701 - if (ts) { 702 - if (!ts->crp) { 703 - /* Supersede thread_stack__event() */ 704 - thread_stack__free(thread); 705 - thread->ts = thread_stack__new(thread, crp); 706 - if (!thread->ts) 707 - return -ENOMEM; 708 - ts = thread->ts; 709 - ts->comm = comm; 710 - } 711 - } else { 712 - thread->ts = thread_stack__new(thread, crp); 713 - if (!thread->ts) 596 + if (ts && !ts->crp) { 597 + /* Supersede thread_stack__event() */ 598 + thread_stack__reset(thread, ts); 599 + ts = NULL; 600 + } 601 + 602 + if (!ts) { 603 + ts = thread_stack__new(thread, sample->cpu, crp); 604 + if (!ts) 714 605 return -ENOMEM; 715 - ts = thread->ts; 716 606 ts->comm = comm; 717 607 } 718 608 ··· 721 621 722 622 /* If the stack is empty, put the current symbol on the stack */ 723 623 if (!ts->cnt) { 724 - err = thread_stack__bottom(thread, ts, sample, from_al, to_al, 725 - ref); 624 + err = thread_stack__bottom(ts, sample, from_al, to_al, ref); 726 625 if (err) 727 626 return err; 728 627 } ··· 770 671 return err; 771 672 } 772 673 773 - size_t thread_stack__depth(struct thread *thread) 674 + size_t thread_stack__depth(struct thread *thread, int cpu) 774 675 { 775 - if (!thread->ts) 676 + struct thread_stack *ts = thread__stack(thread, cpu); 677 + 678 + if (!ts) 776 679 return 0; 777 - return thread->ts->cnt; 680 + return ts->cnt; 778 681 }
+4 -4
tools/perf/util/thread-stack.h
··· 80 80 void *data; 81 81 }; 82 82 83 - int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip, 83 + int thread_stack__event(struct thread *thread, int cpu, u32 flags, u64 from_ip, 84 84 u64 to_ip, u16 insn_len, u64 trace_nr); 85 - void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr); 86 - void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, 85 + void thread_stack__set_trace_nr(struct thread *thread, int cpu, u64 trace_nr); 86 + void thread_stack__sample(struct thread *thread, int cpu, struct ip_callchain *chain, 87 87 size_t sz, u64 ip, u64 kernel_start); 88 88 int thread_stack__flush(struct thread *thread); 89 89 void thread_stack__free(struct thread *thread); 90 - size_t thread_stack__depth(struct thread *thread); 90 + size_t thread_stack__depth(struct thread *thread, int cpu); 91 91 92 92 struct call_return_processor * 93 93 call_return_processor__new(int (*process)(struct call_return *cr, void *data),
+4 -4
tools/power/x86/turbostat/Makefile
··· 9 9 endif 10 10 11 11 turbostat : turbostat.c 12 - CFLAGS += -Wall 13 - CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"' 14 - CFLAGS += -DINTEL_FAMILY_HEADER='"../../../../arch/x86/include/asm/intel-family.h"' 12 + override CFLAGS += -Wall 13 + override CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"' 14 + override CFLAGS += -DINTEL_FAMILY_HEADER='"../../../../arch/x86/include/asm/intel-family.h"' 15 15 16 16 %: %.c 17 17 @mkdir -p $(BUILD_OUTPUT) 18 - $(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@ 18 + $(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@ $(LDFLAGS) 19 19 20 20 .PHONY : clean 21 21 clean :
+3 -3
tools/power/x86/x86_energy_perf_policy/Makefile
··· 9 9 endif 10 10 11 11 x86_energy_perf_policy : x86_energy_perf_policy.c 12 - CFLAGS += -Wall 13 - CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"' 12 + override CFLAGS += -Wall 13 + override CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"' 14 14 15 15 %: %.c 16 16 @mkdir -p $(BUILD_OUTPUT) 17 - $(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@ 17 + $(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@ $(LDFLAGS) 18 18 19 19 .PHONY : clean 20 20 clean :
+4 -4
tools/thermal/tmon/Makefile
··· 6 6 7 7 BINDIR=usr/bin 8 8 WARNFLAGS=-Wall -Wshadow -W -Wformat -Wimplicit-function-declaration -Wimplicit-int 9 - CFLAGS+= -O1 ${WARNFLAGS} 9 + override CFLAGS+= -O1 ${WARNFLAGS} 10 10 # Add "-fstack-protector" only if toolchain supports it. 11 - CFLAGS+= $(call cc-option,-fstack-protector) 11 + override CFLAGS+= $(call cc-option,-fstack-protector-strong) 12 12 CC?= $(CROSS_COMPILE)gcc 13 13 PKG_CONFIG?= pkg-config 14 14 15 - CFLAGS+=-D VERSION=\"$(VERSION)\" 15 + override CFLAGS+=-D VERSION=\"$(VERSION)\" 16 16 LDFLAGS+= 17 17 TARGET=tmon 18 18 ··· 29 29 $(PKG_CONFIG) --libs $(STATIC) panel ncurses 2> /dev/null || \ 30 30 echo -lpanel -lncurses) 31 31 32 - CFLAGS += $(shell $(PKG_CONFIG) --cflags $(STATIC) panelw ncursesw 2> /dev/null || \ 32 + override CFLAGS += $(shell $(PKG_CONFIG) --cflags $(STATIC) panelw ncursesw 2> /dev/null || \ 33 33 $(PKG_CONFIG) --cflags $(STATIC) panel ncurses 2> /dev/null) 34 34 35 35 OBJS = tmon.o tui.o sysfs.o pid.o