diff options
Diffstat (limited to 'tools')
58 files changed, 1886 insertions, 292 deletions
diff --git a/tools/Makefile b/tools/Makefile index 6bf68fe7dd29..f10b64d8c674 100644 --- a/tools/Makefile +++ b/tools/Makefile | |||
@@ -16,6 +16,7 @@ help: | |||
16 | @echo ' gpio - GPIO tools' | 16 | @echo ' gpio - GPIO tools' |
17 | @echo ' hv - tools used when in Hyper-V clients' | 17 | @echo ' hv - tools used when in Hyper-V clients' |
18 | @echo ' iio - IIO tools' | 18 | @echo ' iio - IIO tools' |
19 | @echo ' kvm_stat - top-like utility for displaying kvm statistics' | ||
19 | @echo ' lguest - a minimal 32-bit x86 hypervisor' | 20 | @echo ' lguest - a minimal 32-bit x86 hypervisor' |
20 | @echo ' net - misc networking tools' | 21 | @echo ' net - misc networking tools' |
21 | @echo ' perf - Linux performance measurement and analysis tool' | 22 | @echo ' perf - Linux performance measurement and analysis tool' |
@@ -110,10 +111,13 @@ tmon_install: | |||
110 | freefall_install: | 111 | freefall_install: |
111 | $(call descend,laptop/$(@:_install=),install) | 112 | $(call descend,laptop/$(@:_install=),install) |
112 | 113 | ||
114 | kvm_stat_install: | ||
115 | $(call descend,kvm/$(@:_install=),install) | ||
116 | |||
113 | install: acpi_install cgroup_install cpupower_install hv_install firewire_install lguest_install \ | 117 | install: acpi_install cgroup_install cpupower_install hv_install firewire_install lguest_install \ |
114 | perf_install selftests_install turbostat_install usb_install \ | 118 | perf_install selftests_install turbostat_install usb_install \ |
115 | virtio_install vm_install net_install x86_energy_perf_policy_install \ | 119 | virtio_install vm_install net_install x86_energy_perf_policy_install \ |
116 | tmon_install freefall_install objtool_install | 120 | tmon_install freefall_install objtool_install kvm_stat_install |
117 | 121 | ||
118 | acpi_clean: | 122 | acpi_clean: |
119 | $(call descend,power/acpi,clean) | 123 | $(call descend,power/acpi,clean) |
diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build index ee566e8bd1cf..27f3583193e6 100644 --- a/tools/build/Makefile.build +++ b/tools/build/Makefile.build | |||
@@ -58,8 +58,8 @@ quiet_cmd_mkdir = MKDIR $(dir $@) | |||
58 | quiet_cmd_cc_o_c = CC $@ | 58 | quiet_cmd_cc_o_c = CC $@ |
59 | cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< | 59 | cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< |
60 | 60 | ||
61 | quiet_cmd_cc_i_c = CPP $@ | 61 | quiet_cmd_cpp_i_c = CPP $@ |
62 | cmd_cc_i_c = $(CC) $(c_flags) -E -o $@ $< | 62 | cmd_cpp_i_c = $(CC) $(c_flags) -E -o $@ $< |
63 | 63 | ||
64 | quiet_cmd_cc_s_c = AS $@ | 64 | quiet_cmd_cc_s_c = AS $@ |
65 | cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $< | 65 | cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $< |
@@ -83,11 +83,11 @@ $(OUTPUT)%.o: %.S FORCE | |||
83 | 83 | ||
84 | $(OUTPUT)%.i: %.c FORCE | 84 | $(OUTPUT)%.i: %.c FORCE |
85 | $(call rule_mkdir) | 85 | $(call rule_mkdir) |
86 | $(call if_changed_dep,cc_i_c) | 86 | $(call if_changed_dep,cpp_i_c) |
87 | 87 | ||
88 | $(OUTPUT)%.s: %.S FORCE | 88 | $(OUTPUT)%.s: %.S FORCE |
89 | $(call rule_mkdir) | 89 | $(call rule_mkdir) |
90 | $(call if_changed_dep,cc_i_c) | 90 | $(call if_changed_dep,cpp_i_c) |
91 | 91 | ||
92 | $(OUTPUT)%.s: %.c FORCE | 92 | $(OUTPUT)%.s: %.c FORCE |
93 | $(call rule_mkdir) | 93 | $(call rule_mkdir) |
diff --git a/tools/kvm/kvm_stat/Makefile b/tools/kvm/kvm_stat/Makefile new file mode 100644 index 000000000000..5b1cba57e3b3 --- /dev/null +++ b/tools/kvm/kvm_stat/Makefile | |||
@@ -0,0 +1,41 @@ | |||
1 | include ../../scripts/Makefile.include | ||
2 | include ../../scripts/utilities.mak | ||
3 | BINDIR=usr/bin | ||
4 | MANDIR=usr/share/man | ||
5 | MAN1DIR=$(MANDIR)/man1 | ||
6 | |||
7 | MAN1=kvm_stat.1 | ||
8 | |||
9 | A2X=a2x | ||
10 | a2x_path := $(call get-executable,$(A2X)) | ||
11 | |||
12 | all: man | ||
13 | |||
14 | ifneq ($(findstring $(MAKEFLAGS),s),s) | ||
15 | ifneq ($(V),1) | ||
16 | QUIET_A2X = @echo ' A2X '$@; | ||
17 | endif | ||
18 | endif | ||
19 | |||
20 | %.1: %.txt | ||
21 | ifeq ($(a2x_path),) | ||
22 | $(error "You need to install asciidoc for man pages") | ||
23 | else | ||
24 | $(QUIET_A2X)$(A2X) --doctype manpage --format manpage $< | ||
25 | endif | ||
26 | |||
27 | clean: | ||
28 | rm -f $(MAN1) | ||
29 | |||
30 | man: $(MAN1) | ||
31 | |||
32 | install-man: man | ||
33 | install -d -m 755 $(INSTALL_ROOT)/$(MAN1DIR) | ||
34 | install -m 644 kvm_stat.1 $(INSTALL_ROOT)/$(MAN1DIR) | ||
35 | |||
36 | install-tools: | ||
37 | install -d -m 755 $(INSTALL_ROOT)/$(BINDIR) | ||
38 | install -m 755 -p "kvm_stat" "$(INSTALL_ROOT)/$(BINDIR)/$(TARGET)" | ||
39 | |||
40 | install: install-tools install-man | ||
41 | .PHONY: all clean man install-tools install-man install | ||
diff --git a/tools/kvm/kvm_stat/kvm_stat b/tools/kvm/kvm_stat/kvm_stat new file mode 100755 index 000000000000..581278c58488 --- /dev/null +++ b/tools/kvm/kvm_stat/kvm_stat | |||
@@ -0,0 +1,1127 @@ | |||
1 | #!/usr/bin/python | ||
2 | # | ||
3 | # top-like utility for displaying kvm statistics | ||
4 | # | ||
5 | # Copyright 2006-2008 Qumranet Technologies | ||
6 | # Copyright 2008-2011 Red Hat, Inc. | ||
7 | # | ||
8 | # Authors: | ||
9 | # Avi Kivity <avi@redhat.com> | ||
10 | # | ||
11 | # This work is licensed under the terms of the GNU GPL, version 2. See | ||
12 | # the COPYING file in the top-level directory. | ||
13 | """The kvm_stat module outputs statistics about running KVM VMs | ||
14 | |||
15 | Three different ways of output formatting are available: | ||
16 | - as a top-like text ui | ||
17 | - in a key -> value format | ||
18 | - in an all keys, all values format | ||
19 | |||
20 | The data is sampled from the KVM's debugfs entries and its perf events. | ||
21 | """ | ||
22 | |||
23 | import curses | ||
24 | import sys | ||
25 | import os | ||
26 | import time | ||
27 | import optparse | ||
28 | import ctypes | ||
29 | import fcntl | ||
30 | import resource | ||
31 | import struct | ||
32 | import re | ||
33 | from collections import defaultdict | ||
34 | from time import sleep | ||
35 | |||
36 | VMX_EXIT_REASONS = { | ||
37 | 'EXCEPTION_NMI': 0, | ||
38 | 'EXTERNAL_INTERRUPT': 1, | ||
39 | 'TRIPLE_FAULT': 2, | ||
40 | 'PENDING_INTERRUPT': 7, | ||
41 | 'NMI_WINDOW': 8, | ||
42 | 'TASK_SWITCH': 9, | ||
43 | 'CPUID': 10, | ||
44 | 'HLT': 12, | ||
45 | 'INVLPG': 14, | ||
46 | 'RDPMC': 15, | ||
47 | 'RDTSC': 16, | ||
48 | 'VMCALL': 18, | ||
49 | 'VMCLEAR': 19, | ||
50 | 'VMLAUNCH': 20, | ||
51 | 'VMPTRLD': 21, | ||
52 | 'VMPTRST': 22, | ||
53 | 'VMREAD': 23, | ||
54 | 'VMRESUME': 24, | ||
55 | 'VMWRITE': 25, | ||
56 | 'VMOFF': 26, | ||
57 | 'VMON': 27, | ||
58 | 'CR_ACCESS': 28, | ||
59 | 'DR_ACCESS': 29, | ||
60 | 'IO_INSTRUCTION': 30, | ||
61 | 'MSR_READ': 31, | ||
62 | 'MSR_WRITE': 32, | ||
63 | 'INVALID_STATE': 33, | ||
64 | 'MWAIT_INSTRUCTION': 36, | ||
65 | 'MONITOR_INSTRUCTION': 39, | ||
66 | 'PAUSE_INSTRUCTION': 40, | ||
67 | 'MCE_DURING_VMENTRY': 41, | ||
68 | 'TPR_BELOW_THRESHOLD': 43, | ||
69 | 'APIC_ACCESS': 44, | ||
70 | 'EPT_VIOLATION': 48, | ||
71 | 'EPT_MISCONFIG': 49, | ||
72 | 'WBINVD': 54, | ||
73 | 'XSETBV': 55, | ||
74 | 'APIC_WRITE': 56, | ||
75 | 'INVPCID': 58, | ||
76 | } | ||
77 | |||
78 | SVM_EXIT_REASONS = { | ||
79 | 'READ_CR0': 0x000, | ||
80 | 'READ_CR3': 0x003, | ||
81 | 'READ_CR4': 0x004, | ||
82 | 'READ_CR8': 0x008, | ||
83 | 'WRITE_CR0': 0x010, | ||
84 | 'WRITE_CR3': 0x013, | ||
85 | 'WRITE_CR4': 0x014, | ||
86 | 'WRITE_CR8': 0x018, | ||
87 | 'READ_DR0': 0x020, | ||
88 | 'READ_DR1': 0x021, | ||
89 | 'READ_DR2': 0x022, | ||
90 | 'READ_DR3': 0x023, | ||
91 | 'READ_DR4': 0x024, | ||
92 | 'READ_DR5': 0x025, | ||
93 | 'READ_DR6': 0x026, | ||
94 | 'READ_DR7': 0x027, | ||
95 | 'WRITE_DR0': 0x030, | ||
96 | 'WRITE_DR1': 0x031, | ||
97 | 'WRITE_DR2': 0x032, | ||
98 | 'WRITE_DR3': 0x033, | ||
99 | 'WRITE_DR4': 0x034, | ||
100 | 'WRITE_DR5': 0x035, | ||
101 | 'WRITE_DR6': 0x036, | ||
102 | 'WRITE_DR7': 0x037, | ||
103 | 'EXCP_BASE': 0x040, | ||
104 | 'INTR': 0x060, | ||
105 | 'NMI': 0x061, | ||
106 | 'SMI': 0x062, | ||
107 | 'INIT': 0x063, | ||
108 | 'VINTR': 0x064, | ||
109 | 'CR0_SEL_WRITE': 0x065, | ||
110 | 'IDTR_READ': 0x066, | ||
111 | 'GDTR_READ': 0x067, | ||
112 | 'LDTR_READ': 0x068, | ||
113 | 'TR_READ': 0x069, | ||
114 | 'IDTR_WRITE': 0x06a, | ||
115 | 'GDTR_WRITE': 0x06b, | ||
116 | 'LDTR_WRITE': 0x06c, | ||
117 | 'TR_WRITE': 0x06d, | ||
118 | 'RDTSC': 0x06e, | ||
119 | 'RDPMC': 0x06f, | ||
120 | 'PUSHF': 0x070, | ||
121 | 'POPF': 0x071, | ||
122 | 'CPUID': 0x072, | ||
123 | 'RSM': 0x073, | ||
124 | 'IRET': 0x074, | ||
125 | 'SWINT': 0x075, | ||
126 | 'INVD': 0x076, | ||
127 | 'PAUSE': 0x077, | ||
128 | 'HLT': 0x078, | ||
129 | 'INVLPG': 0x079, | ||
130 | 'INVLPGA': 0x07a, | ||
131 | 'IOIO': 0x07b, | ||
132 | 'MSR': 0x07c, | ||
133 | 'TASK_SWITCH': 0x07d, | ||
134 | 'FERR_FREEZE': 0x07e, | ||
135 | 'SHUTDOWN': 0x07f, | ||
136 | 'VMRUN': 0x080, | ||
137 | 'VMMCALL': 0x081, | ||
138 | 'VMLOAD': 0x082, | ||
139 | 'VMSAVE': 0x083, | ||
140 | 'STGI': 0x084, | ||
141 | 'CLGI': 0x085, | ||
142 | 'SKINIT': 0x086, | ||
143 | 'RDTSCP': 0x087, | ||
144 | 'ICEBP': 0x088, | ||
145 | 'WBINVD': 0x089, | ||
146 | 'MONITOR': 0x08a, | ||
147 | 'MWAIT': 0x08b, | ||
148 | 'MWAIT_COND': 0x08c, | ||
149 | 'XSETBV': 0x08d, | ||
150 | 'NPF': 0x400, | ||
151 | } | ||
152 | |||
153 | # EC definition of HSR (from arch/arm64/include/asm/kvm_arm.h) | ||
154 | AARCH64_EXIT_REASONS = { | ||
155 | 'UNKNOWN': 0x00, | ||
156 | 'WFI': 0x01, | ||
157 | 'CP15_32': 0x03, | ||
158 | 'CP15_64': 0x04, | ||
159 | 'CP14_MR': 0x05, | ||
160 | 'CP14_LS': 0x06, | ||
161 | 'FP_ASIMD': 0x07, | ||
162 | 'CP10_ID': 0x08, | ||
163 | 'CP14_64': 0x0C, | ||
164 | 'ILL_ISS': 0x0E, | ||
165 | 'SVC32': 0x11, | ||
166 | 'HVC32': 0x12, | ||
167 | 'SMC32': 0x13, | ||
168 | 'SVC64': 0x15, | ||
169 | 'HVC64': 0x16, | ||
170 | 'SMC64': 0x17, | ||
171 | 'SYS64': 0x18, | ||
172 | 'IABT': 0x20, | ||
173 | 'IABT_HYP': 0x21, | ||
174 | 'PC_ALIGN': 0x22, | ||
175 | 'DABT': 0x24, | ||
176 | 'DABT_HYP': 0x25, | ||
177 | 'SP_ALIGN': 0x26, | ||
178 | 'FP_EXC32': 0x28, | ||
179 | 'FP_EXC64': 0x2C, | ||
180 | 'SERROR': 0x2F, | ||
181 | 'BREAKPT': 0x30, | ||
182 | 'BREAKPT_HYP': 0x31, | ||
183 | 'SOFTSTP': 0x32, | ||
184 | 'SOFTSTP_HYP': 0x33, | ||
185 | 'WATCHPT': 0x34, | ||
186 | 'WATCHPT_HYP': 0x35, | ||
187 | 'BKPT32': 0x38, | ||
188 | 'VECTOR32': 0x3A, | ||
189 | 'BRK64': 0x3C, | ||
190 | } | ||
191 | |||
192 | # From include/uapi/linux/kvm.h, KVM_EXIT_xxx | ||
193 | USERSPACE_EXIT_REASONS = { | ||
194 | 'UNKNOWN': 0, | ||
195 | 'EXCEPTION': 1, | ||
196 | 'IO': 2, | ||
197 | 'HYPERCALL': 3, | ||
198 | 'DEBUG': 4, | ||
199 | 'HLT': 5, | ||
200 | 'MMIO': 6, | ||
201 | 'IRQ_WINDOW_OPEN': 7, | ||
202 | 'SHUTDOWN': 8, | ||
203 | 'FAIL_ENTRY': 9, | ||
204 | 'INTR': 10, | ||
205 | 'SET_TPR': 11, | ||
206 | 'TPR_ACCESS': 12, | ||
207 | 'S390_SIEIC': 13, | ||
208 | 'S390_RESET': 14, | ||
209 | 'DCR': 15, | ||
210 | 'NMI': 16, | ||
211 | 'INTERNAL_ERROR': 17, | ||
212 | 'OSI': 18, | ||
213 | 'PAPR_HCALL': 19, | ||
214 | 'S390_UCONTROL': 20, | ||
215 | 'WATCHDOG': 21, | ||
216 | 'S390_TSCH': 22, | ||
217 | 'EPR': 23, | ||
218 | 'SYSTEM_EVENT': 24, | ||
219 | } | ||
220 | |||
221 | IOCTL_NUMBERS = { | ||
222 | 'SET_FILTER': 0x40082406, | ||
223 | 'ENABLE': 0x00002400, | ||
224 | 'DISABLE': 0x00002401, | ||
225 | 'RESET': 0x00002403, | ||
226 | } | ||
227 | |||
228 | class Arch(object): | ||
229 | """Encapsulates global architecture specific data. | ||
230 | |||
231 | Contains the performance event open syscall and ioctl numbers, as | ||
232 | well as the VM exit reasons for the architecture it runs on. | ||
233 | |||
234 | """ | ||
235 | @staticmethod | ||
236 | def get_arch(): | ||
237 | machine = os.uname()[4] | ||
238 | |||
239 | if machine.startswith('ppc'): | ||
240 | return ArchPPC() | ||
241 | elif machine.startswith('aarch64'): | ||
242 | return ArchA64() | ||
243 | elif machine.startswith('s390'): | ||
244 | return ArchS390() | ||
245 | else: | ||
246 | # X86_64 | ||
247 | for line in open('/proc/cpuinfo'): | ||
248 | if not line.startswith('flags'): | ||
249 | continue | ||
250 | |||
251 | flags = line.split() | ||
252 | if 'vmx' in flags: | ||
253 | return ArchX86(VMX_EXIT_REASONS) | ||
254 | if 'svm' in flags: | ||
255 | return ArchX86(SVM_EXIT_REASONS) | ||
256 | return | ||
257 | |||
258 | class ArchX86(Arch): | ||
259 | def __init__(self, exit_reasons): | ||
260 | self.sc_perf_evt_open = 298 | ||
261 | self.ioctl_numbers = IOCTL_NUMBERS | ||
262 | self.exit_reasons = exit_reasons | ||
263 | |||
264 | class ArchPPC(Arch): | ||
265 | def __init__(self): | ||
266 | self.sc_perf_evt_open = 319 | ||
267 | self.ioctl_numbers = IOCTL_NUMBERS | ||
268 | self.ioctl_numbers['ENABLE'] = 0x20002400 | ||
269 | self.ioctl_numbers['DISABLE'] = 0x20002401 | ||
270 | self.ioctl_numbers['RESET'] = 0x20002403 | ||
271 | |||
272 | # PPC comes in 32 and 64 bit and some generated ioctl | ||
273 | # numbers depend on the wordsize. | ||
274 | char_ptr_size = ctypes.sizeof(ctypes.c_char_p) | ||
275 | self.ioctl_numbers['SET_FILTER'] = 0x80002406 | char_ptr_size << 16 | ||
276 | self.exit_reasons = {} | ||
277 | |||
278 | class ArchA64(Arch): | ||
279 | def __init__(self): | ||
280 | self.sc_perf_evt_open = 241 | ||
281 | self.ioctl_numbers = IOCTL_NUMBERS | ||
282 | self.exit_reasons = AARCH64_EXIT_REASONS | ||
283 | |||
284 | class ArchS390(Arch): | ||
285 | def __init__(self): | ||
286 | self.sc_perf_evt_open = 331 | ||
287 | self.ioctl_numbers = IOCTL_NUMBERS | ||
288 | self.exit_reasons = None | ||
289 | |||
290 | ARCH = Arch.get_arch() | ||
291 | |||
292 | |||
293 | def walkdir(path): | ||
294 | """Returns os.walk() data for specified directory. | ||
295 | |||
296 | As it is only a wrapper it returns the same 3-tuple of (dirpath, | ||
297 | dirnames, filenames). | ||
298 | """ | ||
299 | return next(os.walk(path)) | ||
300 | |||
301 | |||
302 | def parse_int_list(list_string): | ||
303 | """Returns an int list from a string of comma separated integers and | ||
304 | integer ranges.""" | ||
305 | integers = [] | ||
306 | members = list_string.split(',') | ||
307 | |||
308 | for member in members: | ||
309 | if '-' not in member: | ||
310 | integers.append(int(member)) | ||
311 | else: | ||
312 | int_range = member.split('-') | ||
313 | integers.extend(range(int(int_range[0]), | ||
314 | int(int_range[1]) + 1)) | ||
315 | |||
316 | return integers | ||
317 | |||
318 | |||
319 | def get_online_cpus(): | ||
320 | """Returns a list of cpu id integers.""" | ||
321 | with open('/sys/devices/system/cpu/online') as cpu_list: | ||
322 | cpu_string = cpu_list.readline() | ||
323 | return parse_int_list(cpu_string) | ||
324 | |||
325 | |||
326 | def get_filters(): | ||
327 | """Returns a dict of trace events, their filter ids and | ||
328 | the values that can be filtered. | ||
329 | |||
330 | Trace events can be filtered for special values by setting a | ||
331 | filter string via an ioctl. The string normally has the format | ||
332 | identifier==value. For each filter a new event will be created, to | ||
333 | be able to distinguish the events. | ||
334 | |||
335 | """ | ||
336 | filters = {} | ||
337 | filters['kvm_userspace_exit'] = ('reason', USERSPACE_EXIT_REASONS) | ||
338 | if ARCH.exit_reasons: | ||
339 | filters['kvm_exit'] = ('exit_reason', ARCH.exit_reasons) | ||
340 | return filters | ||
341 | |||
342 | libc = ctypes.CDLL('libc.so.6', use_errno=True) | ||
343 | syscall = libc.syscall | ||
344 | |||
345 | class perf_event_attr(ctypes.Structure): | ||
346 | """Struct that holds the necessary data to set up a trace event. | ||
347 | |||
348 | For an extensive explanation see perf_event_open(2) and | ||
349 | include/uapi/linux/perf_event.h, struct perf_event_attr | ||
350 | |||
351 | All fields that are not initialized in the constructor are 0. | ||
352 | |||
353 | """ | ||
354 | _fields_ = [('type', ctypes.c_uint32), | ||
355 | ('size', ctypes.c_uint32), | ||
356 | ('config', ctypes.c_uint64), | ||
357 | ('sample_freq', ctypes.c_uint64), | ||
358 | ('sample_type', ctypes.c_uint64), | ||
359 | ('read_format', ctypes.c_uint64), | ||
360 | ('flags', ctypes.c_uint64), | ||
361 | ('wakeup_events', ctypes.c_uint32), | ||
362 | ('bp_type', ctypes.c_uint32), | ||
363 | ('bp_addr', ctypes.c_uint64), | ||
364 | ('bp_len', ctypes.c_uint64), | ||
365 | ] | ||
366 | |||
367 | def __init__(self): | ||
368 | super(self.__class__, self).__init__() | ||
369 | self.type = PERF_TYPE_TRACEPOINT | ||
370 | self.size = ctypes.sizeof(self) | ||
371 | self.read_format = PERF_FORMAT_GROUP | ||
372 | |||
373 | def perf_event_open(attr, pid, cpu, group_fd, flags): | ||
374 | """Wrapper for the sys_perf_evt_open() syscall. | ||
375 | |||
376 | Used to set up performance events, returns a file descriptor or -1 | ||
377 | on error. | ||
378 | |||
379 | Attributes are: | ||
380 | - syscall number | ||
381 | - struct perf_event_attr * | ||
382 | - pid or -1 to monitor all pids | ||
383 | - cpu number or -1 to monitor all cpus | ||
384 | - The file descriptor of the group leader or -1 to create a group. | ||
385 | - flags | ||
386 | |||
387 | """ | ||
388 | return syscall(ARCH.sc_perf_evt_open, ctypes.pointer(attr), | ||
389 | ctypes.c_int(pid), ctypes.c_int(cpu), | ||
390 | ctypes.c_int(group_fd), ctypes.c_long(flags)) | ||
391 | |||
392 | PERF_TYPE_TRACEPOINT = 2 | ||
393 | PERF_FORMAT_GROUP = 1 << 3 | ||
394 | |||
395 | PATH_DEBUGFS_TRACING = '/sys/kernel/debug/tracing' | ||
396 | PATH_DEBUGFS_KVM = '/sys/kernel/debug/kvm' | ||
397 | |||
398 | class Group(object): | ||
399 | """Represents a perf event group.""" | ||
400 | |||
401 | def __init__(self): | ||
402 | self.events = [] | ||
403 | |||
404 | def add_event(self, event): | ||
405 | self.events.append(event) | ||
406 | |||
407 | def read(self): | ||
408 | """Returns a dict with 'event name: value' for all events in the | ||
409 | group. | ||
410 | |||
411 | Values are read by reading from the file descriptor of the | ||
412 | event that is the group leader. See perf_event_open(2) for | ||
413 | details. | ||
414 | |||
415 | Read format for the used event configuration is: | ||
416 | struct read_format { | ||
417 | u64 nr; /* The number of events */ | ||
418 | struct { | ||
419 | u64 value; /* The value of the event */ | ||
420 | } values[nr]; | ||
421 | }; | ||
422 | |||
423 | """ | ||
424 | length = 8 * (1 + len(self.events)) | ||
425 | read_format = 'xxxxxxxx' + 'Q' * len(self.events) | ||
426 | return dict(zip([event.name for event in self.events], | ||
427 | struct.unpack(read_format, | ||
428 | os.read(self.events[0].fd, length)))) | ||
429 | |||
430 | class Event(object): | ||
431 | """Represents a performance event and manages its life cycle.""" | ||
432 | def __init__(self, name, group, trace_cpu, trace_pid, trace_point, | ||
433 | trace_filter, trace_set='kvm'): | ||
434 | self.name = name | ||
435 | self.fd = None | ||
436 | self.setup_event(group, trace_cpu, trace_pid, trace_point, | ||
437 | trace_filter, trace_set) | ||
438 | |||
439 | def __del__(self): | ||
440 | """Closes the event's file descriptor. | ||
441 | |||
442 | As no python file object was created for the file descriptor, | ||
443 | python will not reference count the descriptor and will not | ||
444 | close it itself automatically, so we do it. | ||
445 | |||
446 | """ | ||
447 | if self.fd: | ||
448 | os.close(self.fd) | ||
449 | |||
450 | def setup_event_attribute(self, trace_set, trace_point): | ||
451 | """Returns an initialized ctype perf_event_attr struct.""" | ||
452 | |||
453 | id_path = os.path.join(PATH_DEBUGFS_TRACING, 'events', trace_set, | ||
454 | trace_point, 'id') | ||
455 | |||
456 | event_attr = perf_event_attr() | ||
457 | event_attr.config = int(open(id_path).read()) | ||
458 | return event_attr | ||
459 | |||
460 | def setup_event(self, group, trace_cpu, trace_pid, trace_point, | ||
461 | trace_filter, trace_set): | ||
462 | """Sets up the perf event in Linux. | ||
463 | |||
464 | Issues the syscall to register the event in the kernel and | ||
465 | then sets the optional filter. | ||
466 | |||
467 | """ | ||
468 | |||
469 | event_attr = self.setup_event_attribute(trace_set, trace_point) | ||
470 | |||
471 | # First event will be group leader. | ||
472 | group_leader = -1 | ||
473 | |||
474 | # All others have to pass the leader's descriptor instead. | ||
475 | if group.events: | ||
476 | group_leader = group.events[0].fd | ||
477 | |||
478 | fd = perf_event_open(event_attr, trace_pid, | ||
479 | trace_cpu, group_leader, 0) | ||
480 | if fd == -1: | ||
481 | err = ctypes.get_errno() | ||
482 | raise OSError(err, os.strerror(err), | ||
483 | 'while calling sys_perf_event_open().') | ||
484 | |||
485 | if trace_filter: | ||
486 | fcntl.ioctl(fd, ARCH.ioctl_numbers['SET_FILTER'], | ||
487 | trace_filter) | ||
488 | |||
489 | self.fd = fd | ||
490 | |||
491 | def enable(self): | ||
492 | """Enables the trace event in the kernel. | ||
493 | |||
494 | Enabling the group leader makes reading counters from it and the | ||
495 | events under it possible. | ||
496 | |||
497 | """ | ||
498 | fcntl.ioctl(self.fd, ARCH.ioctl_numbers['ENABLE'], 0) | ||
499 | |||
500 | def disable(self): | ||
501 | """Disables the trace event in the kernel. | ||
502 | |||
503 | Disabling the group leader makes reading all counters under it | ||
504 | impossible. | ||
505 | |||
506 | """ | ||
507 | fcntl.ioctl(self.fd, ARCH.ioctl_numbers['DISABLE'], 0) | ||
508 | |||
509 | def reset(self): | ||
510 | """Resets the count of the trace event in the kernel.""" | ||
511 | fcntl.ioctl(self.fd, ARCH.ioctl_numbers['RESET'], 0) | ||
512 | |||
513 | class TracepointProvider(object): | ||
514 | """Data provider for the stats class. | ||
515 | |||
516 | Manages the events/groups from which it acquires its data. | ||
517 | |||
518 | """ | ||
519 | def __init__(self): | ||
520 | self.group_leaders = [] | ||
521 | self.filters = get_filters() | ||
522 | self._fields = self.get_available_fields() | ||
523 | self._pid = 0 | ||
524 | |||
525 | def get_available_fields(self): | ||
526 | """Returns a list of available event's of format 'event name(filter | ||
527 | name)'. | ||
528 | |||
529 | All available events have directories under | ||
530 | /sys/kernel/debug/tracing/events/ which export information | ||
531 | about the specific event. Therefore, listing the dirs gives us | ||
532 | a list of all available events. | ||
533 | |||
534 | Some events like the vm exit reasons can be filtered for | ||
535 | specific values. To take account for that, the routine below | ||
536 | creates special fields with the following format: | ||
537 | event name(filter name) | ||
538 | |||
539 | """ | ||
540 | path = os.path.join(PATH_DEBUGFS_TRACING, 'events', 'kvm') | ||
541 | fields = walkdir(path)[1] | ||
542 | extra = [] | ||
543 | for field in fields: | ||
544 | if field in self.filters: | ||
545 | filter_name_, filter_dicts = self.filters[field] | ||
546 | for name in filter_dicts: | ||
547 | extra.append(field + '(' + name + ')') | ||
548 | fields += extra | ||
549 | return fields | ||
550 | |||
551 | def setup_traces(self): | ||
552 | """Creates all event and group objects needed to be able to retrieve | ||
553 | data.""" | ||
554 | if self._pid > 0: | ||
555 | # Fetch list of all threads of the monitored pid, as qemu | ||
556 | # starts a thread for each vcpu. | ||
557 | path = os.path.join('/proc', str(self._pid), 'task') | ||
558 | groupids = walkdir(path)[1] | ||
559 | else: | ||
560 | groupids = get_online_cpus() | ||
561 | |||
562 | # The constant is needed as a buffer for python libs, std | ||
563 | # streams and other files that the script opens. | ||
564 | newlim = len(groupids) * len(self._fields) + 50 | ||
565 | try: | ||
566 | softlim_, hardlim = resource.getrlimit(resource.RLIMIT_NOFILE) | ||
567 | |||
568 | if hardlim < newlim: | ||
569 | # Now we need CAP_SYS_RESOURCE, to increase the hard limit. | ||
570 | resource.setrlimit(resource.RLIMIT_NOFILE, (newlim, newlim)) | ||
571 | else: | ||
572 | # Raising the soft limit is sufficient. | ||
573 | resource.setrlimit(resource.RLIMIT_NOFILE, (newlim, hardlim)) | ||
574 | |||
575 | except ValueError: | ||
576 | sys.exit("NOFILE rlimit could not be raised to {0}".format(newlim)) | ||
577 | |||
578 | for groupid in groupids: | ||
579 | group = Group() | ||
580 | for name in self._fields: | ||
581 | tracepoint = name | ||
582 | tracefilter = None | ||
583 | match = re.match(r'(.*)\((.*)\)', name) | ||
584 | if match: | ||
585 | tracepoint, sub = match.groups() | ||
586 | tracefilter = ('%s==%d\0' % | ||
587 | (self.filters[tracepoint][0], | ||
588 | self.filters[tracepoint][1][sub])) | ||
589 | |||
590 | # From perf_event_open(2): | ||
591 | # pid > 0 and cpu == -1 | ||
592 | # This measures the specified process/thread on any CPU. | ||
593 | # | ||
594 | # pid == -1 and cpu >= 0 | ||
595 | # This measures all processes/threads on the specified CPU. | ||
596 | trace_cpu = groupid if self._pid == 0 else -1 | ||
597 | trace_pid = int(groupid) if self._pid != 0 else -1 | ||
598 | |||
599 | group.add_event(Event(name=name, | ||
600 | group=group, | ||
601 | trace_cpu=trace_cpu, | ||
602 | trace_pid=trace_pid, | ||
603 | trace_point=tracepoint, | ||
604 | trace_filter=tracefilter)) | ||
605 | |||
606 | self.group_leaders.append(group) | ||
607 | |||
608 | def available_fields(self): | ||
609 | return self.get_available_fields() | ||
610 | |||
611 | @property | ||
612 | def fields(self): | ||
613 | return self._fields | ||
614 | |||
615 | @fields.setter | ||
616 | def fields(self, fields): | ||
617 | """Enables/disables the (un)wanted events""" | ||
618 | self._fields = fields | ||
619 | for group in self.group_leaders: | ||
620 | for index, event in enumerate(group.events): | ||
621 | if event.name in fields: | ||
622 | event.reset() | ||
623 | event.enable() | ||
624 | else: | ||
625 | # Do not disable the group leader. | ||
626 | # It would disable all of its events. | ||
627 | if index != 0: | ||
628 | event.disable() | ||
629 | |||
630 | @property | ||
631 | def pid(self): | ||
632 | return self._pid | ||
633 | |||
634 | @pid.setter | ||
635 | def pid(self, pid): | ||
636 | """Changes the monitored pid by setting new traces.""" | ||
637 | self._pid = pid | ||
638 | # The garbage collector will get rid of all Event/Group | ||
639 | # objects and open files after removing the references. | ||
640 | self.group_leaders = [] | ||
641 | self.setup_traces() | ||
642 | self.fields = self._fields | ||
643 | |||
644 | def read(self): | ||
645 | """Returns 'event name: current value' for all enabled events.""" | ||
646 | ret = defaultdict(int) | ||
647 | for group in self.group_leaders: | ||
648 | for name, val in group.read().iteritems(): | ||
649 | if name in self._fields: | ||
650 | ret[name] += val | ||
651 | return ret | ||
652 | |||
653 | class DebugfsProvider(object): | ||
654 | """Provides data from the files that KVM creates in the kvm debugfs | ||
655 | folder.""" | ||
656 | def __init__(self): | ||
657 | self._fields = self.get_available_fields() | ||
658 | self._pid = 0 | ||
659 | self.do_read = True | ||
660 | |||
661 | def get_available_fields(self): | ||
662 | """"Returns a list of available fields. | ||
663 | |||
664 | The fields are all available KVM debugfs files | ||
665 | |||
666 | """ | ||
667 | return walkdir(PATH_DEBUGFS_KVM)[2] | ||
668 | |||
669 | @property | ||
670 | def fields(self): | ||
671 | return self._fields | ||
672 | |||
673 | @fields.setter | ||
674 | def fields(self, fields): | ||
675 | self._fields = fields | ||
676 | |||
677 | @property | ||
678 | def pid(self): | ||
679 | return self._pid | ||
680 | |||
681 | @pid.setter | ||
682 | def pid(self, pid): | ||
683 | if pid != 0: | ||
684 | self._pid = pid | ||
685 | |||
686 | vms = walkdir(PATH_DEBUGFS_KVM)[1] | ||
687 | if len(vms) == 0: | ||
688 | self.do_read = False | ||
689 | |||
690 | self.paths = filter(lambda x: "{}-".format(pid) in x, vms) | ||
691 | |||
692 | else: | ||
693 | self.paths = [''] | ||
694 | self.do_read = True | ||
695 | |||
696 | def read(self): | ||
697 | """Returns a dict with format:'file name / field -> current value'.""" | ||
698 | results = {} | ||
699 | |||
700 | # If no debugfs filtering support is available, then don't read. | ||
701 | if not self.do_read: | ||
702 | return results | ||
703 | |||
704 | for path in self.paths: | ||
705 | for field in self._fields: | ||
706 | results[field] = results.get(field, 0) \ | ||
707 | + self.read_field(field, path) | ||
708 | |||
709 | return results | ||
710 | |||
711 | def read_field(self, field, path): | ||
712 | """Returns the value of a single field from a specific VM.""" | ||
713 | try: | ||
714 | return int(open(os.path.join(PATH_DEBUGFS_KVM, | ||
715 | path, | ||
716 | field)) | ||
717 | .read()) | ||
718 | except IOError: | ||
719 | return 0 | ||
720 | |||
721 | class Stats(object): | ||
722 | """Manages the data providers and the data they provide. | ||
723 | |||
724 | It is used to set filters on the provider's data and collect all | ||
725 | provider data. | ||
726 | |||
727 | """ | ||
728 | def __init__(self, providers, pid, fields=None): | ||
729 | self.providers = providers | ||
730 | self._pid_filter = pid | ||
731 | self._fields_filter = fields | ||
732 | self.values = {} | ||
733 | self.update_provider_pid() | ||
734 | self.update_provider_filters() | ||
735 | |||
736 | def update_provider_filters(self): | ||
737 | """Propagates fields filters to providers.""" | ||
738 | def wanted(key): | ||
739 | if not self._fields_filter: | ||
740 | return True | ||
741 | return re.match(self._fields_filter, key) is not None | ||
742 | |||
743 | # As we reset the counters when updating the fields we can | ||
744 | # also clear the cache of old values. | ||
745 | self.values = {} | ||
746 | for provider in self.providers: | ||
747 | provider_fields = [key for key in provider.get_available_fields() | ||
748 | if wanted(key)] | ||
749 | provider.fields = provider_fields | ||
750 | |||
751 | def update_provider_pid(self): | ||
752 | """Propagates pid filters to providers.""" | ||
753 | for provider in self.providers: | ||
754 | provider.pid = self._pid_filter | ||
755 | |||
756 | @property | ||
757 | def fields_filter(self): | ||
758 | return self._fields_filter | ||
759 | |||
760 | @fields_filter.setter | ||
761 | def fields_filter(self, fields_filter): | ||
762 | self._fields_filter = fields_filter | ||
763 | self.update_provider_filters() | ||
764 | |||
765 | @property | ||
766 | def pid_filter(self): | ||
767 | return self._pid_filter | ||
768 | |||
769 | @pid_filter.setter | ||
770 | def pid_filter(self, pid): | ||
771 | self._pid_filter = pid | ||
772 | self.values = {} | ||
773 | self.update_provider_pid() | ||
774 | |||
775 | def get(self): | ||
776 | """Returns a dict with field -> (value, delta to last value) of all | ||
777 | provider data.""" | ||
778 | for provider in self.providers: | ||
779 | new = provider.read() | ||
780 | for key in provider.fields: | ||
781 | oldval = self.values.get(key, (0, 0)) | ||
782 | newval = new.get(key, 0) | ||
783 | newdelta = None | ||
784 | if oldval is not None: | ||
785 | newdelta = newval - oldval[0] | ||
786 | self.values[key] = (newval, newdelta) | ||
787 | return self.values | ||
788 | |||
789 | LABEL_WIDTH = 40 | ||
790 | NUMBER_WIDTH = 10 | ||
791 | |||
792 | class Tui(object): | ||
793 | """Instruments curses to draw a nice text ui.""" | ||
794 | def __init__(self, stats): | ||
795 | self.stats = stats | ||
796 | self.screen = None | ||
797 | self.drilldown = False | ||
798 | self.update_drilldown() | ||
799 | |||
800 | def __enter__(self): | ||
801 | """Initialises curses for later use. Based on curses.wrapper | ||
802 | implementation from the Python standard library.""" | ||
803 | self.screen = curses.initscr() | ||
804 | curses.noecho() | ||
805 | curses.cbreak() | ||
806 | |||
807 | # The try/catch works around a minor bit of | ||
808 | # over-conscientiousness in the curses module, the error | ||
809 | # return from C start_color() is ignorable. | ||
810 | try: | ||
811 | curses.start_color() | ||
812 | except: | ||
813 | pass | ||
814 | |||
815 | curses.use_default_colors() | ||
816 | return self | ||
817 | |||
818 | def __exit__(self, *exception): | ||
819 | """Resets the terminal to its normal state. Based on curses.wrappre | ||
820 | implementation from the Python standard library.""" | ||
821 | if self.screen: | ||
822 | self.screen.keypad(0) | ||
823 | curses.echo() | ||
824 | curses.nocbreak() | ||
825 | curses.endwin() | ||
826 | |||
827 | def update_drilldown(self): | ||
828 | """Sets or removes a filter that only allows fields without braces.""" | ||
829 | if not self.stats.fields_filter: | ||
830 | self.stats.fields_filter = r'^[^\(]*$' | ||
831 | |||
832 | elif self.stats.fields_filter == r'^[^\(]*$': | ||
833 | self.stats.fields_filter = None | ||
834 | |||
835 | def update_pid(self, pid): | ||
836 | """Propagates pid selection to stats object.""" | ||
837 | self.stats.pid_filter = pid | ||
838 | |||
839 | def refresh(self, sleeptime): | ||
840 | """Refreshes on-screen data.""" | ||
841 | self.screen.erase() | ||
842 | if self.stats.pid_filter > 0: | ||
843 | self.screen.addstr(0, 0, 'kvm statistics - pid {0}' | ||
844 | .format(self.stats.pid_filter), | ||
845 | curses.A_BOLD) | ||
846 | else: | ||
847 | self.screen.addstr(0, 0, 'kvm statistics - summary', curses.A_BOLD) | ||
848 | self.screen.addstr(2, 1, 'Event') | ||
849 | self.screen.addstr(2, 1 + LABEL_WIDTH + NUMBER_WIDTH - | ||
850 | len('Total'), 'Total') | ||
851 | self.screen.addstr(2, 1 + LABEL_WIDTH + NUMBER_WIDTH + 8 - | ||
852 | len('Current'), 'Current') | ||
853 | row = 3 | ||
854 | stats = self.stats.get() | ||
855 | def sortkey(x): | ||
856 | if stats[x][1]: | ||
857 | return (-stats[x][1], -stats[x][0]) | ||
858 | else: | ||
859 | return (0, -stats[x][0]) | ||
860 | for key in sorted(stats.keys(), key=sortkey): | ||
861 | |||
862 | if row >= self.screen.getmaxyx()[0]: | ||
863 | break | ||
864 | values = stats[key] | ||
865 | if not values[0] and not values[1]: | ||
866 | break | ||
867 | col = 1 | ||
868 | self.screen.addstr(row, col, key) | ||
869 | col += LABEL_WIDTH | ||
870 | self.screen.addstr(row, col, '%10d' % (values[0],)) | ||
871 | col += NUMBER_WIDTH | ||
872 | if values[1] is not None: | ||
873 | self.screen.addstr(row, col, '%8d' % (values[1] / sleeptime,)) | ||
874 | row += 1 | ||
875 | self.screen.refresh() | ||
876 | |||
877 | def show_filter_selection(self): | ||
878 | """Draws filter selection mask. | ||
879 | |||
880 | Asks for a valid regex and sets the fields filter accordingly. | ||
881 | |||
882 | """ | ||
883 | while True: | ||
884 | self.screen.erase() | ||
885 | self.screen.addstr(0, 0, | ||
886 | "Show statistics for events matching a regex.", | ||
887 | curses.A_BOLD) | ||
888 | self.screen.addstr(2, 0, | ||
889 | "Current regex: {0}" | ||
890 | .format(self.stats.fields_filter)) | ||
891 | self.screen.addstr(3, 0, "New regex: ") | ||
892 | curses.echo() | ||
893 | regex = self.screen.getstr() | ||
894 | curses.noecho() | ||
895 | if len(regex) == 0: | ||
896 | return | ||
897 | try: | ||
898 | re.compile(regex) | ||
899 | self.stats.fields_filter = regex | ||
900 | return | ||
901 | except re.error: | ||
902 | continue | ||
903 | |||
904 | def show_vm_selection(self): | ||
905 | """Draws PID selection mask. | ||
906 | |||
907 | Asks for a pid until a valid pid or 0 has been entered. | ||
908 | |||
909 | """ | ||
910 | while True: | ||
911 | self.screen.erase() | ||
912 | self.screen.addstr(0, 0, | ||
913 | 'Show statistics for specific pid.', | ||
914 | curses.A_BOLD) | ||
915 | self.screen.addstr(1, 0, | ||
916 | 'This might limit the shown data to the trace ' | ||
917 | 'statistics.') | ||
918 | |||
919 | curses.echo() | ||
920 | self.screen.addstr(3, 0, "Pid [0 or pid]: ") | ||
921 | pid = self.screen.getstr() | ||
922 | curses.noecho() | ||
923 | |||
924 | try: | ||
925 | pid = int(pid) | ||
926 | |||
927 | if pid == 0: | ||
928 | self.update_pid(pid) | ||
929 | break | ||
930 | else: | ||
931 | if not os.path.isdir(os.path.join('/proc/', str(pid))): | ||
932 | continue | ||
933 | else: | ||
934 | self.update_pid(pid) | ||
935 | break | ||
936 | |||
937 | except ValueError: | ||
938 | continue | ||
939 | |||
940 | def show_stats(self): | ||
941 | """Refreshes the screen and processes user input.""" | ||
942 | sleeptime = 0.25 | ||
943 | while True: | ||
944 | self.refresh(sleeptime) | ||
945 | curses.halfdelay(int(sleeptime * 10)) | ||
946 | sleeptime = 3 | ||
947 | try: | ||
948 | char = self.screen.getkey() | ||
949 | if char == 'x': | ||
950 | self.drilldown = not self.drilldown | ||
951 | self.update_drilldown() | ||
952 | if char == 'q': | ||
953 | break | ||
954 | if char == 'f': | ||
955 | self.show_filter_selection() | ||
956 | if char == 'p': | ||
957 | self.show_vm_selection() | ||
958 | except KeyboardInterrupt: | ||
959 | break | ||
960 | except curses.error: | ||
961 | continue | ||
962 | |||
963 | def batch(stats): | ||
964 | """Prints statistics in a key, value format.""" | ||
965 | s = stats.get() | ||
966 | time.sleep(1) | ||
967 | s = stats.get() | ||
968 | for key in sorted(s.keys()): | ||
969 | values = s[key] | ||
970 | print '%-42s%10d%10d' % (key, values[0], values[1]) | ||
971 | |||
972 | def log(stats): | ||
973 | """Prints statistics as reiterating key block, multiple value blocks.""" | ||
974 | keys = sorted(stats.get().iterkeys()) | ||
975 | def banner(): | ||
976 | for k in keys: | ||
977 | print '%s' % k, | ||
978 | |||
979 | def statline(): | ||
980 | s = stats.get() | ||
981 | for k in keys: | ||
982 | print ' %9d' % s[k][1], | ||
983 | |||
984 | line = 0 | ||
985 | banner_repeat = 20 | ||
986 | while True: | ||
987 | time.sleep(1) | ||
988 | if line % banner_repeat == 0: | ||
989 | banner() | ||
990 | statline() | ||
991 | line += 1 | ||
992 | |||
993 | def get_options(): | ||
994 | """Returns processed program arguments.""" | ||
995 | description_text = """ | ||
996 | This script displays various statistics about VMs running under KVM. | ||
997 | The statistics are gathered from the KVM debugfs entries and / or the | ||
998 | currently available perf traces. | ||
999 | |||
1000 | The monitoring takes additional cpu cycles and might affect the VM's | ||
1001 | performance. | ||
1002 | |||
1003 | Requirements: | ||
1004 | - Access to: | ||
1005 | /sys/kernel/debug/kvm | ||
1006 | /sys/kernel/debug/trace/events/* | ||
1007 | /proc/pid/task | ||
1008 | - /proc/sys/kernel/perf_event_paranoid < 1 if user has no | ||
1009 | CAP_SYS_ADMIN and perf events are used. | ||
1010 | - CAP_SYS_RESOURCE if the hard limit is not high enough to allow | ||
1011 | the large number of files that are possibly opened. | ||
1012 | """ | ||
1013 | |||
1014 | class PlainHelpFormatter(optparse.IndentedHelpFormatter): | ||
1015 | def format_description(self, description): | ||
1016 | if description: | ||
1017 | return description + "\n" | ||
1018 | else: | ||
1019 | return "" | ||
1020 | |||
1021 | optparser = optparse.OptionParser(description=description_text, | ||
1022 | formatter=PlainHelpFormatter()) | ||
1023 | optparser.add_option('-1', '--once', '--batch', | ||
1024 | action='store_true', | ||
1025 | default=False, | ||
1026 | dest='once', | ||
1027 | help='run in batch mode for one second', | ||
1028 | ) | ||
1029 | optparser.add_option('-l', '--log', | ||
1030 | action='store_true', | ||
1031 | default=False, | ||
1032 | dest='log', | ||
1033 | help='run in logging mode (like vmstat)', | ||
1034 | ) | ||
1035 | optparser.add_option('-t', '--tracepoints', | ||
1036 | action='store_true', | ||
1037 | default=False, | ||
1038 | dest='tracepoints', | ||
1039 | help='retrieve statistics from tracepoints', | ||
1040 | ) | ||
1041 | optparser.add_option('-d', '--debugfs', | ||
1042 | action='store_true', | ||
1043 | default=False, | ||
1044 | dest='debugfs', | ||
1045 | help='retrieve statistics from debugfs', | ||
1046 | ) | ||
1047 | optparser.add_option('-f', '--fields', | ||
1048 | action='store', | ||
1049 | default=None, | ||
1050 | dest='fields', | ||
1051 | help='fields to display (regex)', | ||
1052 | ) | ||
1053 | optparser.add_option('-p', '--pid', | ||
1054 | action='store', | ||
1055 | default=0, | ||
1056 | type=int, | ||
1057 | dest='pid', | ||
1058 | help='restrict statistics to pid', | ||
1059 | ) | ||
1060 | (options, _) = optparser.parse_args(sys.argv) | ||
1061 | return options | ||
1062 | |||
1063 | def get_providers(options): | ||
1064 | """Returns a list of data providers depending on the passed options.""" | ||
1065 | providers = [] | ||
1066 | |||
1067 | if options.tracepoints: | ||
1068 | providers.append(TracepointProvider()) | ||
1069 | if options.debugfs: | ||
1070 | providers.append(DebugfsProvider()) | ||
1071 | if len(providers) == 0: | ||
1072 | providers.append(TracepointProvider()) | ||
1073 | |||
1074 | return providers | ||
1075 | |||
1076 | def check_access(options): | ||
1077 | """Exits if the current user can't access all needed directories.""" | ||
1078 | if not os.path.exists('/sys/kernel/debug'): | ||
1079 | sys.stderr.write('Please enable CONFIG_DEBUG_FS in your kernel.') | ||
1080 | sys.exit(1) | ||
1081 | |||
1082 | if not os.path.exists(PATH_DEBUGFS_KVM): | ||
1083 | sys.stderr.write("Please make sure, that debugfs is mounted and " | ||
1084 | "readable by the current user:\n" | ||
1085 | "('mount -t debugfs debugfs /sys/kernel/debug')\n" | ||
1086 | "Also ensure, that the kvm modules are loaded.\n") | ||
1087 | sys.exit(1) | ||
1088 | |||
1089 | if not os.path.exists(PATH_DEBUGFS_TRACING) and (options.tracepoints | ||
1090 | or not options.debugfs): | ||
1091 | sys.stderr.write("Please enable CONFIG_TRACING in your kernel " | ||
1092 | "when using the option -t (default).\n" | ||
1093 | "If it is enabled, make {0} readable by the " | ||
1094 | "current user.\n" | ||
1095 | .format(PATH_DEBUGFS_TRACING)) | ||
1096 | if options.tracepoints: | ||
1097 | sys.exit(1) | ||
1098 | |||
1099 | sys.stderr.write("Falling back to debugfs statistics!\n") | ||
1100 | options.debugfs = True | ||
1101 | sleep(5) | ||
1102 | |||
1103 | return options | ||
1104 | |||
1105 | def main(): | ||
1106 | options = get_options() | ||
1107 | options = check_access(options) | ||
1108 | |||
1109 | if (options.pid > 0 and | ||
1110 | not os.path.isdir(os.path.join('/proc/', | ||
1111 | str(options.pid)))): | ||
1112 | sys.stderr.write('Did you use a (unsupported) tid instead of a pid?\n') | ||
1113 | sys.exit('Specified pid does not exist.') | ||
1114 | |||
1115 | providers = get_providers(options) | ||
1116 | stats = Stats(providers, options.pid, fields=options.fields) | ||
1117 | |||
1118 | if options.log: | ||
1119 | log(stats) | ||
1120 | elif not options.once: | ||
1121 | with Tui(stats) as tui: | ||
1122 | tui.show_stats() | ||
1123 | else: | ||
1124 | batch(stats) | ||
1125 | |||
1126 | if __name__ == "__main__": | ||
1127 | main() | ||
diff --git a/tools/kvm/kvm_stat/kvm_stat.txt b/tools/kvm/kvm_stat/kvm_stat.txt new file mode 100644 index 000000000000..b92a153d7115 --- /dev/null +++ b/tools/kvm/kvm_stat/kvm_stat.txt | |||
@@ -0,0 +1,63 @@ | |||
1 | kvm_stat(1) | ||
2 | =========== | ||
3 | |||
4 | NAME | ||
5 | ---- | ||
6 | kvm_stat - Report KVM kernel module event counters | ||
7 | |||
8 | SYNOPSIS | ||
9 | -------- | ||
10 | [verse] | ||
11 | 'kvm_stat' [OPTION]... | ||
12 | |||
13 | DESCRIPTION | ||
14 | ----------- | ||
15 | kvm_stat prints counts of KVM kernel module trace events. These events signify | ||
16 | state transitions such as guest mode entry and exit. | ||
17 | |||
18 | This tool is useful for observing guest behavior from the host perspective. | ||
19 | Often conclusions about performance or buggy behavior can be drawn from the | ||
20 | output. | ||
21 | |||
22 | The set of KVM kernel module trace events may be specific to the kernel version | ||
23 | or architecture. It is best to check the KVM kernel module source code for the | ||
24 | meaning of events. | ||
25 | |||
26 | OPTIONS | ||
27 | ------- | ||
28 | -1:: | ||
29 | --once:: | ||
30 | --batch:: | ||
31 | run in batch mode for one second | ||
32 | |||
33 | -l:: | ||
34 | --log:: | ||
35 | run in logging mode (like vmstat) | ||
36 | |||
37 | -t:: | ||
38 | --tracepoints:: | ||
39 | retrieve statistics from tracepoints | ||
40 | |||
41 | -d:: | ||
42 | --debugfs:: | ||
43 | retrieve statistics from debugfs | ||
44 | |||
45 | -p<pid>:: | ||
46 | --pid=<pid>:: | ||
47 | limit statistics to one virtual machine (pid) | ||
48 | |||
49 | -f<fields>:: | ||
50 | --fields=<fields>:: | ||
51 | fields to display (regex) | ||
52 | |||
53 | -h:: | ||
54 | --help:: | ||
55 | show help message | ||
56 | |||
57 | SEE ALSO | ||
58 | -------- | ||
59 | 'perf'(1), 'trace-cmd'(1) | ||
60 | |||
61 | AUTHOR | ||
62 | ------ | ||
63 | Stefan Hajnoczi <stefanha@redhat.com> | ||
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile index 6765c7e949f3..f094f3c4ed84 100644 --- a/tools/objtool/Makefile +++ b/tools/objtool/Makefile | |||
@@ -30,6 +30,10 @@ INCLUDES := -I$(srctree)/tools/include | |||
30 | CFLAGS += -Wall -Werror $(EXTRA_WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES) | 30 | CFLAGS += -Wall -Werror $(EXTRA_WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES) |
31 | LDFLAGS += -lelf $(LIBSUBCMD) | 31 | LDFLAGS += -lelf $(LIBSUBCMD) |
32 | 32 | ||
33 | # Allow old libelf to be used: | ||
34 | elfshdr := $(shell echo '\#include <libelf.h>' | $(CC) $(CFLAGS) -x c -E - | grep elf_getshdr) | ||
35 | CFLAGS += $(if $(elfshdr),,-DLIBELF_USE_DEPRECATED) | ||
36 | |||
33 | AWK = awk | 37 | AWK = awk |
34 | export srctree OUTPUT CFLAGS ARCH AWK | 38 | export srctree OUTPUT CFLAGS ARCH AWK |
35 | include $(srctree)/tools/build/Makefile.include | 39 | include $(srctree)/tools/build/Makefile.include |
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c index e8a1e69eb92c..25d803148f5c 100644 --- a/tools/objtool/builtin-check.c +++ b/tools/objtool/builtin-check.c | |||
@@ -122,10 +122,14 @@ static bool ignore_func(struct objtool_file *file, struct symbol *func) | |||
122 | 122 | ||
123 | /* check for STACK_FRAME_NON_STANDARD */ | 123 | /* check for STACK_FRAME_NON_STANDARD */ |
124 | if (file->whitelist && file->whitelist->rela) | 124 | if (file->whitelist && file->whitelist->rela) |
125 | list_for_each_entry(rela, &file->whitelist->rela->rela_list, list) | 125 | list_for_each_entry(rela, &file->whitelist->rela->rela_list, list) { |
126 | if (rela->sym->sec == func->sec && | 126 | if (rela->sym->type == STT_SECTION && |
127 | rela->sym->sec == func->sec && | ||
127 | rela->addend == func->offset) | 128 | rela->addend == func->offset) |
128 | return true; | 129 | return true; |
130 | if (rela->sym->type == STT_FUNC && rela->sym == func) | ||
131 | return true; | ||
132 | } | ||
129 | 133 | ||
130 | /* check if it has a context switching instruction */ | 134 | /* check if it has a context switching instruction */ |
131 | func_for_each_insn(file, func, insn) | 135 | func_for_each_insn(file, func, insn) |
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h index 7f3e00a2f907..aa1ff6596684 100644 --- a/tools/objtool/elf.h +++ b/tools/objtool/elf.h | |||
@@ -23,6 +23,11 @@ | |||
23 | #include <linux/list.h> | 23 | #include <linux/list.h> |
24 | #include <linux/hashtable.h> | 24 | #include <linux/hashtable.h> |
25 | 25 | ||
26 | #ifdef LIBELF_USE_DEPRECATED | ||
27 | # define elf_getshdrnum elf_getshnum | ||
28 | # define elf_getshdrstrndx elf_getshstrndx | ||
29 | #endif | ||
30 | |||
26 | struct section { | 31 | struct section { |
27 | struct list_head list; | 32 | struct list_head list; |
28 | GElf_Shdr sh; | 33 | GElf_Shdr sh; |
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index ebaf849e30ef..9cbddc290aff 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt | |||
@@ -103,12 +103,13 @@ OPTIONS | |||
103 | 103 | ||
104 | If --branch-stack option is used, following sort keys are also | 104 | If --branch-stack option is used, following sort keys are also |
105 | available: | 105 | available: |
106 | dso_from, dso_to, symbol_from, symbol_to, mispredict. | ||
107 | 106 | ||
108 | - dso_from: name of library or module branched from | 107 | - dso_from: name of library or module branched from |
109 | - dso_to: name of library or module branched to | 108 | - dso_to: name of library or module branched to |
110 | - symbol_from: name of function branched from | 109 | - symbol_from: name of function branched from |
111 | - symbol_to: name of function branched to | 110 | - symbol_to: name of function branched to |
111 | - srcline_from: source file and line branched from | ||
112 | - srcline_to: source file and line branched to | ||
112 | - mispredict: "N" for predicted branch, "Y" for mispredicted branch | 113 | - mispredict: "N" for predicted branch, "Y" for mispredicted branch |
113 | - in_tx: branch in TSX transaction | 114 | - in_tx: branch in TSX transaction |
114 | - abort: TSX transaction abort. | 115 | - abort: TSX transaction abort. |
@@ -248,7 +249,7 @@ OPTIONS | |||
248 | Note that when using the --itrace option the synthesized callchain size | 249 | Note that when using the --itrace option the synthesized callchain size |
249 | will override this value if the synthesized callchain size is bigger. | 250 | will override this value if the synthesized callchain size is bigger. |
250 | 251 | ||
251 | Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise. | 252 | Default: 127 |
252 | 253 | ||
253 | -G:: | 254 | -G:: |
254 | --inverted:: | 255 | --inverted:: |
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index a856a1095893..4fc44c75263f 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt | |||
@@ -267,7 +267,7 @@ include::itrace.txt[] | |||
267 | Note that when using the --itrace option the synthesized callchain size | 267 | Note that when using the --itrace option the synthesized callchain size |
268 | will override this value if the synthesized callchain size is bigger. | 268 | will override this value if the synthesized callchain size is bigger. |
269 | 269 | ||
270 | Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise. | 270 | Default: 127 |
271 | 271 | ||
272 | --ns:: | 272 | --ns:: |
273 | Use 9 decimal places when displaying time (i.e. show the nanoseconds) | 273 | Use 9 decimal places when displaying time (i.e. show the nanoseconds) |
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index 6afe20121bc0..1ab0782369b1 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt | |||
@@ -143,7 +143,8 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. | |||
143 | Implies '--call-graph dwarf' when --call-graph not present on the | 143 | Implies '--call-graph dwarf' when --call-graph not present on the |
144 | command line, on systems where DWARF unwinding was built in. | 144 | command line, on systems where DWARF unwinding was built in. |
145 | 145 | ||
146 | Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise. | 146 | Default: /proc/sys/kernel/perf_event_max_stack when present for |
147 | live sessions (without --input/-i), 127 otherwise. | ||
147 | 148 | ||
148 | --min-stack:: | 149 | --min-stack:: |
149 | Set the stack depth limit when parsing the callchain, anything | 150 | Set the stack depth limit when parsing the callchain, anything |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 814158393656..25c81734a950 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -324,8 +324,9 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) | |||
324 | OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing, | 324 | OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing, |
325 | "Skip symbols that cannot be annotated"), | 325 | "Skip symbols that cannot be annotated"), |
326 | OPT_STRING('C', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"), | 326 | OPT_STRING('C', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"), |
327 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", | 327 | OPT_CALLBACK(0, "symfs", NULL, "directory", |
328 | "Look for files with symbols relative to this directory"), | 328 | "Look for files with symbols relative to this directory", |
329 | symbol__config_symfs), | ||
329 | OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, | 330 | OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, |
330 | "Interleave source code with assembly code (default)"), | 331 | "Interleave source code with assembly code (default)"), |
331 | OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, | 332 | OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, |
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c index 632efc6b79a0..d75bded21fe0 100644 --- a/tools/perf/builtin-buildid-cache.c +++ b/tools/perf/builtin-buildid-cache.c | |||
@@ -119,8 +119,8 @@ static int build_id_cache__add_kcore(const char *filename, bool force) | |||
119 | if (build_id_cache__kcore_buildid(from_dir, sbuildid) < 0) | 119 | if (build_id_cache__kcore_buildid(from_dir, sbuildid) < 0) |
120 | return -1; | 120 | return -1; |
121 | 121 | ||
122 | scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s", | 122 | scnprintf(to_dir, sizeof(to_dir), "%s/%s/%s", |
123 | buildid_dir, sbuildid); | 123 | buildid_dir, DSO__NAME_KCORE, sbuildid); |
124 | 124 | ||
125 | if (!force && | 125 | if (!force && |
126 | !build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) { | 126 | !build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) { |
@@ -131,8 +131,8 @@ static int build_id_cache__add_kcore(const char *filename, bool force) | |||
131 | if (build_id_cache__kcore_dir(dir, sizeof(dir))) | 131 | if (build_id_cache__kcore_dir(dir, sizeof(dir))) |
132 | return -1; | 132 | return -1; |
133 | 133 | ||
134 | scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s", | 134 | scnprintf(to_dir, sizeof(to_dir), "%s/%s/%s/%s", |
135 | buildid_dir, sbuildid, dir); | 135 | buildid_dir, DSO__NAME_KCORE, sbuildid, dir); |
136 | 136 | ||
137 | if (mkdir_p(to_dir, 0755)) | 137 | if (mkdir_p(to_dir, 0755)) |
138 | return -1; | 138 | return -1; |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 9ce354f469dc..f7645a42708e 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -812,8 +812,9 @@ static const struct option options[] = { | |||
812 | OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator", | 812 | OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator", |
813 | "separator for columns, no spaces will be added between " | 813 | "separator for columns, no spaces will be added between " |
814 | "columns '.' is reserved."), | 814 | "columns '.' is reserved."), |
815 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", | 815 | OPT_CALLBACK(0, "symfs", NULL, "directory", |
816 | "Look for files with symbols relative to this directory"), | 816 | "Look for files with symbols relative to this directory", |
817 | symbol__config_symfs), | ||
817 | OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."), | 818 | OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."), |
818 | OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", | 819 | OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", |
819 | "How to display percentage of filtered entries", parse_filter_percentage), | 820 | "How to display percentage of filtered entries", parse_filter_percentage), |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index f3679c44d3f3..dc3fcb597e4c 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <unistd.h> | 40 | #include <unistd.h> |
41 | #include <sched.h> | 41 | #include <sched.h> |
42 | #include <sys/mman.h> | 42 | #include <sys/mman.h> |
43 | #include <asm/bug.h> | ||
43 | 44 | ||
44 | 45 | ||
45 | struct record { | 46 | struct record { |
@@ -82,27 +83,87 @@ static int process_synthesized_event(struct perf_tool *tool, | |||
82 | return record__write(rec, event, event->header.size); | 83 | return record__write(rec, event, event->header.size); |
83 | } | 84 | } |
84 | 85 | ||
86 | static int | ||
87 | backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end) | ||
88 | { | ||
89 | struct perf_event_header *pheader; | ||
90 | u64 evt_head = head; | ||
91 | int size = mask + 1; | ||
92 | |||
93 | pr_debug2("backward_rb_find_range: buf=%p, head=%"PRIx64"\n", buf, head); | ||
94 | pheader = (struct perf_event_header *)(buf + (head & mask)); | ||
95 | *start = head; | ||
96 | while (true) { | ||
97 | if (evt_head - head >= (unsigned int)size) { | ||
98 | pr_debug("Finshed reading backward ring buffer: rewind\n"); | ||
99 | if (evt_head - head > (unsigned int)size) | ||
100 | evt_head -= pheader->size; | ||
101 | *end = evt_head; | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | pheader = (struct perf_event_header *)(buf + (evt_head & mask)); | ||
106 | |||
107 | if (pheader->size == 0) { | ||
108 | pr_debug("Finshed reading backward ring buffer: get start\n"); | ||
109 | *end = evt_head; | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | evt_head += pheader->size; | ||
114 | pr_debug3("move evt_head: %"PRIx64"\n", evt_head); | ||
115 | } | ||
116 | WARN_ONCE(1, "Shouldn't get here\n"); | ||
117 | return -1; | ||
118 | } | ||
119 | |||
120 | static int | ||
121 | rb_find_range(struct perf_evlist *evlist, | ||
122 | void *data, int mask, u64 head, u64 old, | ||
123 | u64 *start, u64 *end) | ||
124 | { | ||
125 | if (!evlist->backward) { | ||
126 | *start = old; | ||
127 | *end = head; | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | return backward_rb_find_range(data, mask, head, start, end); | ||
132 | } | ||
133 | |||
85 | static int record__mmap_read(struct record *rec, int idx) | 134 | static int record__mmap_read(struct record *rec, int idx) |
86 | { | 135 | { |
87 | struct perf_mmap *md = &rec->evlist->mmap[idx]; | 136 | struct perf_mmap *md = &rec->evlist->mmap[idx]; |
88 | u64 head = perf_mmap__read_head(md); | 137 | u64 head = perf_mmap__read_head(md); |
89 | u64 old = md->prev; | 138 | u64 old = md->prev; |
139 | u64 end = head, start = old; | ||
90 | unsigned char *data = md->base + page_size; | 140 | unsigned char *data = md->base + page_size; |
91 | unsigned long size; | 141 | unsigned long size; |
92 | void *buf; | 142 | void *buf; |
93 | int rc = 0; | 143 | int rc = 0; |
94 | 144 | ||
95 | if (old == head) | 145 | if (rb_find_range(rec->evlist, data, md->mask, head, |
146 | old, &start, &end)) | ||
147 | return -1; | ||
148 | |||
149 | if (start == end) | ||
96 | return 0; | 150 | return 0; |
97 | 151 | ||
98 | rec->samples++; | 152 | rec->samples++; |
99 | 153 | ||
100 | size = head - old; | 154 | size = end - start; |
155 | if (size > (unsigned long)(md->mask) + 1) { | ||
156 | WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n"); | ||
157 | |||
158 | md->prev = head; | ||
159 | perf_evlist__mmap_consume(rec->evlist, idx); | ||
160 | return 0; | ||
161 | } | ||
101 | 162 | ||
102 | if ((old & md->mask) + size != (head & md->mask)) { | 163 | if ((start & md->mask) + size != (end & md->mask)) { |
103 | buf = &data[old & md->mask]; | 164 | buf = &data[start & md->mask]; |
104 | size = md->mask + 1 - (old & md->mask); | 165 | size = md->mask + 1 - (start & md->mask); |
105 | old += size; | 166 | start += size; |
106 | 167 | ||
107 | if (record__write(rec, buf, size) < 0) { | 168 | if (record__write(rec, buf, size) < 0) { |
108 | rc = -1; | 169 | rc = -1; |
@@ -110,16 +171,16 @@ static int record__mmap_read(struct record *rec, int idx) | |||
110 | } | 171 | } |
111 | } | 172 | } |
112 | 173 | ||
113 | buf = &data[old & md->mask]; | 174 | buf = &data[start & md->mask]; |
114 | size = head - old; | 175 | size = end - start; |
115 | old += size; | 176 | start += size; |
116 | 177 | ||
117 | if (record__write(rec, buf, size) < 0) { | 178 | if (record__write(rec, buf, size) < 0) { |
118 | rc = -1; | 179 | rc = -1; |
119 | goto out; | 180 | goto out; |
120 | } | 181 | } |
121 | 182 | ||
122 | md->prev = old; | 183 | md->prev = head; |
123 | perf_evlist__mmap_consume(rec->evlist, idx); | 184 | perf_evlist__mmap_consume(rec->evlist, idx); |
124 | out: | 185 | out: |
125 | return rc; | 186 | return rc; |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 87d40e3c4078..a87cb338bdf1 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -691,7 +691,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
691 | .ordered_events = true, | 691 | .ordered_events = true, |
692 | .ordering_requires_timestamps = true, | 692 | .ordering_requires_timestamps = true, |
693 | }, | 693 | }, |
694 | .max_stack = sysctl_perf_event_max_stack, | 694 | .max_stack = PERF_MAX_STACK_DEPTH, |
695 | .pretty_printing_style = "normal", | 695 | .pretty_printing_style = "normal", |
696 | .socket_filter = -1, | 696 | .socket_filter = -1, |
697 | }; | 697 | }; |
@@ -770,8 +770,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
770 | "columns '.' is reserved."), | 770 | "columns '.' is reserved."), |
771 | OPT_BOOLEAN('U', "hide-unresolved", &symbol_conf.hide_unresolved, | 771 | OPT_BOOLEAN('U', "hide-unresolved", &symbol_conf.hide_unresolved, |
772 | "Only display entries resolved to a symbol"), | 772 | "Only display entries resolved to a symbol"), |
773 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", | 773 | OPT_CALLBACK(0, "symfs", NULL, "directory", |
774 | "Look for files with symbols relative to this directory"), | 774 | "Look for files with symbols relative to this directory", |
775 | symbol__config_symfs), | ||
775 | OPT_STRING('C', "cpu", &report.cpu_list, "cpu", | 776 | OPT_STRING('C', "cpu", &report.cpu_list, "cpu", |
776 | "list of cpus to profile"), | 777 | "list of cpus to profile"), |
777 | OPT_BOOLEAN('I', "show-info", &report.show_full_info, | 778 | OPT_BOOLEAN('I', "show-info", &report.show_full_info, |
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index efca81679bb3..e3ce2f34d3ad 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -2010,8 +2010,9 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
2010 | "file", "kallsyms pathname"), | 2010 | "file", "kallsyms pathname"), |
2011 | OPT_BOOLEAN('G', "hide-call-graph", &no_callchain, | 2011 | OPT_BOOLEAN('G', "hide-call-graph", &no_callchain, |
2012 | "When printing symbols do not display call chain"), | 2012 | "When printing symbols do not display call chain"), |
2013 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", | 2013 | OPT_CALLBACK(0, "symfs", NULL, "directory", |
2014 | "Look for files with symbols relative to this directory"), | 2014 | "Look for files with symbols relative to this directory", |
2015 | symbol__config_symfs), | ||
2015 | OPT_CALLBACK('F', "fields", NULL, "str", | 2016 | OPT_CALLBACK('F', "fields", NULL, "str", |
2016 | "comma separated output fields prepend with 'type:'. " | 2017 | "comma separated output fields prepend with 'type:'. " |
2017 | "Valid types: hw,sw,trace,raw. " | 2018 | "Valid types: hw,sw,trace,raw. " |
@@ -2067,8 +2068,6 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
2067 | NULL | 2068 | NULL |
2068 | }; | 2069 | }; |
2069 | 2070 | ||
2070 | scripting_max_stack = sysctl_perf_event_max_stack; | ||
2071 | |||
2072 | setup_scripting(); | 2071 | setup_scripting(); |
2073 | 2072 | ||
2074 | argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage, | 2073 | argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage, |
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index e459b685a4e9..ee7ada78d86f 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -66,6 +66,7 @@ | |||
66 | #include <stdlib.h> | 66 | #include <stdlib.h> |
67 | #include <sys/prctl.h> | 67 | #include <sys/prctl.h> |
68 | #include <locale.h> | 68 | #include <locale.h> |
69 | #include <math.h> | ||
69 | 70 | ||
70 | #define DEFAULT_SEPARATOR " " | 71 | #define DEFAULT_SEPARATOR " " |
71 | #define CNTR_NOT_SUPPORTED "<not supported>" | 72 | #define CNTR_NOT_SUPPORTED "<not supported>" |
@@ -991,12 +992,12 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg) | |||
991 | const char *fmt; | 992 | const char *fmt; |
992 | 993 | ||
993 | if (csv_output) { | 994 | if (csv_output) { |
994 | fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s"; | 995 | fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s"; |
995 | } else { | 996 | } else { |
996 | if (big_num) | 997 | if (big_num) |
997 | fmt = sc != 1.0 ? "%'18.2f%s" : "%'18.0f%s"; | 998 | fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s"; |
998 | else | 999 | else |
999 | fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s"; | 1000 | fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s"; |
1000 | } | 1001 | } |
1001 | 1002 | ||
1002 | aggr_printout(evsel, id, nr); | 1003 | aggr_printout(evsel, id, nr); |
@@ -1909,6 +1910,9 @@ static int add_default_attributes(void) | |||
1909 | } | 1910 | } |
1910 | 1911 | ||
1911 | if (!evsel_list->nr_entries) { | 1912 | if (!evsel_list->nr_entries) { |
1913 | if (target__has_cpu(&target)) | ||
1914 | default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK; | ||
1915 | |||
1912 | if (perf_evlist__add_default_attrs(evsel_list, default_attrs0) < 0) | 1916 | if (perf_evlist__add_default_attrs(evsel_list, default_attrs0) < 0) |
1913 | return -1; | 1917 | return -1; |
1914 | if (pmu_have_event("cpu", "stalled-cycles-frontend")) { | 1918 | if (pmu_have_event("cpu", "stalled-cycles-frontend")) { |
@@ -2000,7 +2004,7 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused, | |||
2000 | union perf_event *event, | 2004 | union perf_event *event, |
2001 | struct perf_session *session) | 2005 | struct perf_session *session) |
2002 | { | 2006 | { |
2003 | struct stat_round_event *round = &event->stat_round; | 2007 | struct stat_round_event *stat_round = &event->stat_round; |
2004 | struct perf_evsel *counter; | 2008 | struct perf_evsel *counter; |
2005 | struct timespec tsh, *ts = NULL; | 2009 | struct timespec tsh, *ts = NULL; |
2006 | const char **argv = session->header.env.cmdline_argv; | 2010 | const char **argv = session->header.env.cmdline_argv; |
@@ -2009,12 +2013,12 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused, | |||
2009 | evlist__for_each(evsel_list, counter) | 2013 | evlist__for_each(evsel_list, counter) |
2010 | perf_stat_process_counter(&stat_config, counter); | 2014 | perf_stat_process_counter(&stat_config, counter); |
2011 | 2015 | ||
2012 | if (round->type == PERF_STAT_ROUND_TYPE__FINAL) | 2016 | if (stat_round->type == PERF_STAT_ROUND_TYPE__FINAL) |
2013 | update_stats(&walltime_nsecs_stats, round->time); | 2017 | update_stats(&walltime_nsecs_stats, stat_round->time); |
2014 | 2018 | ||
2015 | if (stat_config.interval && round->time) { | 2019 | if (stat_config.interval && stat_round->time) { |
2016 | tsh.tv_sec = round->time / NSECS_PER_SEC; | 2020 | tsh.tv_sec = stat_round->time / NSECS_PER_SEC; |
2017 | tsh.tv_nsec = round->time % NSECS_PER_SEC; | 2021 | tsh.tv_nsec = stat_round->time % NSECS_PER_SEC; |
2018 | ts = &tsh; | 2022 | ts = &tsh; |
2019 | } | 2023 | } |
2020 | 2024 | ||
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 40cc9bb3506c..733a55422d03 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c | |||
@@ -1945,8 +1945,9 @@ int cmd_timechart(int argc, const char **argv, | |||
1945 | OPT_CALLBACK('p', "process", NULL, "process", | 1945 | OPT_CALLBACK('p', "process", NULL, "process", |
1946 | "process selector. Pass a pid or process name.", | 1946 | "process selector. Pass a pid or process name.", |
1947 | parse_process), | 1947 | parse_process), |
1948 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", | 1948 | OPT_CALLBACK(0, "symfs", NULL, "directory", |
1949 | "Look for files with symbols relative to this directory"), | 1949 | "Look for files with symbols relative to this directory", |
1950 | symbol__config_symfs), | ||
1950 | OPT_INTEGER('n', "proc-num", &tchart.proc_num, | 1951 | OPT_INTEGER('n', "proc-num", &tchart.proc_num, |
1951 | "min. number of tasks to print"), | 1952 | "min. number of tasks to print"), |
1952 | OPT_BOOLEAN('t', "topology", &tchart.topology, | 1953 | OPT_BOOLEAN('t', "topology", &tchart.topology, |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 1793da585676..2a6cc254ad0c 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -732,7 +732,7 @@ static void perf_event__process_sample(struct perf_tool *tool, | |||
732 | if (machine__resolve(machine, &al, sample) < 0) | 732 | if (machine__resolve(machine, &al, sample) < 0) |
733 | return; | 733 | return; |
734 | 734 | ||
735 | if (!top->kptr_restrict_warned && | 735 | if (!machine->kptr_restrict_warned && |
736 | symbol_conf.kptr_restrict && | 736 | symbol_conf.kptr_restrict && |
737 | al.cpumode == PERF_RECORD_MISC_KERNEL) { | 737 | al.cpumode == PERF_RECORD_MISC_KERNEL) { |
738 | ui__warning( | 738 | ui__warning( |
@@ -743,7 +743,7 @@ static void perf_event__process_sample(struct perf_tool *tool, | |||
743 | " modules" : ""); | 743 | " modules" : ""); |
744 | if (use_browser <= 0) | 744 | if (use_browser <= 0) |
745 | sleep(5); | 745 | sleep(5); |
746 | top->kptr_restrict_warned = true; | 746 | machine->kptr_restrict_warned = true; |
747 | } | 747 | } |
748 | 748 | ||
749 | if (al.sym == NULL) { | 749 | if (al.sym == NULL) { |
@@ -759,7 +759,7 @@ static void perf_event__process_sample(struct perf_tool *tool, | |||
759 | * --hide-kernel-symbols, even if the user specifies an | 759 | * --hide-kernel-symbols, even if the user specifies an |
760 | * invalid --vmlinux ;-) | 760 | * invalid --vmlinux ;-) |
761 | */ | 761 | */ |
762 | if (!top->kptr_restrict_warned && !top->vmlinux_warned && | 762 | if (!machine->kptr_restrict_warned && !top->vmlinux_warned && |
763 | al.map == machine->vmlinux_maps[MAP__FUNCTION] && | 763 | al.map == machine->vmlinux_maps[MAP__FUNCTION] && |
764 | RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { | 764 | RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { |
765 | if (symbol_conf.vmlinux_name) { | 765 | if (symbol_conf.vmlinux_name) { |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 6e5c325148e4..5c50fe70d6b3 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -576,84 +576,54 @@ static struct syscall_fmt { | |||
576 | bool hexret; | 576 | bool hexret; |
577 | } syscall_fmts[] = { | 577 | } syscall_fmts[] = { |
578 | { .name = "access", .errmsg = true, | 578 | { .name = "access", .errmsg = true, |
579 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ | 579 | .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, }, |
580 | [1] = SCA_ACCMODE, /* mode */ }, }, | ||
581 | { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, | 580 | { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, |
582 | { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), }, | 581 | { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), }, |
583 | { .name = "brk", .hexret = true, | 582 | { .name = "brk", .hexret = true, |
584 | .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, | 583 | .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, |
585 | { .name = "chdir", .errmsg = true, | 584 | { .name = "chdir", .errmsg = true, }, |
586 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | 585 | { .name = "chmod", .errmsg = true, }, |
587 | { .name = "chmod", .errmsg = true, | 586 | { .name = "chroot", .errmsg = true, }, |
588 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
589 | { .name = "chroot", .errmsg = true, | ||
590 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
591 | { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), }, | 587 | { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), }, |
592 | { .name = "clone", .errpid = true, }, | 588 | { .name = "clone", .errpid = true, }, |
593 | { .name = "close", .errmsg = true, | 589 | { .name = "close", .errmsg = true, |
594 | .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, | 590 | .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, |
595 | { .name = "connect", .errmsg = true, }, | 591 | { .name = "connect", .errmsg = true, }, |
596 | { .name = "creat", .errmsg = true, | 592 | { .name = "creat", .errmsg = true, }, |
597 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | 593 | { .name = "dup", .errmsg = true, }, |
598 | { .name = "dup", .errmsg = true, | 594 | { .name = "dup2", .errmsg = true, }, |
599 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 595 | { .name = "dup3", .errmsg = true, }, |
600 | { .name = "dup2", .errmsg = true, | ||
601 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
602 | { .name = "dup3", .errmsg = true, | ||
603 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
604 | { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), }, | 596 | { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), }, |
605 | { .name = "eventfd2", .errmsg = true, | 597 | { .name = "eventfd2", .errmsg = true, |
606 | .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, }, | 598 | .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, }, |
607 | { .name = "faccessat", .errmsg = true, | 599 | { .name = "faccessat", .errmsg = true, }, |
608 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ | 600 | { .name = "fadvise64", .errmsg = true, }, |
609 | [1] = SCA_FILENAME, /* filename */ }, }, | 601 | { .name = "fallocate", .errmsg = true, }, |
610 | { .name = "fadvise64", .errmsg = true, | 602 | { .name = "fchdir", .errmsg = true, }, |
611 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 603 | { .name = "fchmod", .errmsg = true, }, |
612 | { .name = "fallocate", .errmsg = true, | ||
613 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
614 | { .name = "fchdir", .errmsg = true, | ||
615 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
616 | { .name = "fchmod", .errmsg = true, | ||
617 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
618 | { .name = "fchmodat", .errmsg = true, | 604 | { .name = "fchmodat", .errmsg = true, |
619 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ | 605 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, |
620 | [1] = SCA_FILENAME, /* filename */ }, }, | 606 | { .name = "fchown", .errmsg = true, }, |
621 | { .name = "fchown", .errmsg = true, | ||
622 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
623 | { .name = "fchownat", .errmsg = true, | 607 | { .name = "fchownat", .errmsg = true, |
624 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ | 608 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, |
625 | [1] = SCA_FILENAME, /* filename */ }, }, | ||
626 | { .name = "fcntl", .errmsg = true, | 609 | { .name = "fcntl", .errmsg = true, |
627 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 610 | .arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ }, |
628 | [1] = SCA_STRARRAY, /* cmd */ }, | ||
629 | .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, }, | 611 | .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, }, |
630 | { .name = "fdatasync", .errmsg = true, | 612 | { .name = "fdatasync", .errmsg = true, }, |
631 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
632 | { .name = "flock", .errmsg = true, | 613 | { .name = "flock", .errmsg = true, |
633 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 614 | .arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, }, |
634 | [1] = SCA_FLOCK, /* cmd */ }, }, | 615 | { .name = "fsetxattr", .errmsg = true, }, |
635 | { .name = "fsetxattr", .errmsg = true, | 616 | { .name = "fstat", .errmsg = true, .alias = "newfstat", }, |
636 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 617 | { .name = "fstatat", .errmsg = true, .alias = "newfstatat", }, |
637 | { .name = "fstat", .errmsg = true, .alias = "newfstat", | 618 | { .name = "fstatfs", .errmsg = true, }, |
638 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 619 | { .name = "fsync", .errmsg = true, }, |
639 | { .name = "fstatat", .errmsg = true, .alias = "newfstatat", | 620 | { .name = "ftruncate", .errmsg = true, }, |
640 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ | ||
641 | [1] = SCA_FILENAME, /* filename */ }, }, | ||
642 | { .name = "fstatfs", .errmsg = true, | ||
643 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
644 | { .name = "fsync", .errmsg = true, | ||
645 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
646 | { .name = "ftruncate", .errmsg = true, | ||
647 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
648 | { .name = "futex", .errmsg = true, | 621 | { .name = "futex", .errmsg = true, |
649 | .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, }, | 622 | .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, }, |
650 | { .name = "futimesat", .errmsg = true, | 623 | { .name = "futimesat", .errmsg = true, |
651 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ | 624 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, |
652 | [1] = SCA_FILENAME, /* filename */ }, }, | 625 | { .name = "getdents", .errmsg = true, }, |
653 | { .name = "getdents", .errmsg = true, | 626 | { .name = "getdents64", .errmsg = true, }, |
654 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
655 | { .name = "getdents64", .errmsg = true, | ||
656 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
657 | { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), }, | 627 | { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), }, |
658 | { .name = "getpid", .errpid = true, }, | 628 | { .name = "getpid", .errpid = true, }, |
659 | { .name = "getpgid", .errpid = true, }, | 629 | { .name = "getpgid", .errpid = true, }, |
@@ -661,12 +631,10 @@ static struct syscall_fmt { | |||
661 | { .name = "getrandom", .errmsg = true, | 631 | { .name = "getrandom", .errmsg = true, |
662 | .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, }, | 632 | .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, }, |
663 | { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, | 633 | { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, |
664 | { .name = "getxattr", .errmsg = true, | 634 | { .name = "getxattr", .errmsg = true, }, |
665 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | 635 | { .name = "inotify_add_watch", .errmsg = true, }, |
666 | { .name = "inotify_add_watch", .errmsg = true, | ||
667 | .arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, }, | ||
668 | { .name = "ioctl", .errmsg = true, | 636 | { .name = "ioctl", .errmsg = true, |
669 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 637 | .arg_scnprintf = { |
670 | #if defined(__i386__) || defined(__x86_64__) | 638 | #if defined(__i386__) || defined(__x86_64__) |
671 | /* | 639 | /* |
672 | * FIXME: Make this available to all arches. | 640 | * FIXME: Make this available to all arches. |
@@ -680,41 +648,28 @@ static struct syscall_fmt { | |||
680 | { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), }, | 648 | { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), }, |
681 | { .name = "kill", .errmsg = true, | 649 | { .name = "kill", .errmsg = true, |
682 | .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, | 650 | .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, |
683 | { .name = "lchown", .errmsg = true, | 651 | { .name = "lchown", .errmsg = true, }, |
684 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | 652 | { .name = "lgetxattr", .errmsg = true, }, |
685 | { .name = "lgetxattr", .errmsg = true, | ||
686 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
687 | { .name = "linkat", .errmsg = true, | 653 | { .name = "linkat", .errmsg = true, |
688 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, | 654 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, |
689 | { .name = "listxattr", .errmsg = true, | 655 | { .name = "listxattr", .errmsg = true, }, |
690 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | 656 | { .name = "llistxattr", .errmsg = true, }, |
691 | { .name = "llistxattr", .errmsg = true, | 657 | { .name = "lremovexattr", .errmsg = true, }, |
692 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
693 | { .name = "lremovexattr", .errmsg = true, | ||
694 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
695 | { .name = "lseek", .errmsg = true, | 658 | { .name = "lseek", .errmsg = true, |
696 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 659 | .arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ }, |
697 | [2] = SCA_STRARRAY, /* whence */ }, | ||
698 | .arg_parm = { [2] = &strarray__whences, /* whence */ }, }, | 660 | .arg_parm = { [2] = &strarray__whences, /* whence */ }, }, |
699 | { .name = "lsetxattr", .errmsg = true, | 661 | { .name = "lsetxattr", .errmsg = true, }, |
700 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | 662 | { .name = "lstat", .errmsg = true, .alias = "newlstat", }, |
701 | { .name = "lstat", .errmsg = true, .alias = "newlstat", | 663 | { .name = "lsxattr", .errmsg = true, }, |
702 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
703 | { .name = "lsxattr", .errmsg = true, | ||
704 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
705 | { .name = "madvise", .errmsg = true, | 664 | { .name = "madvise", .errmsg = true, |
706 | .arg_scnprintf = { [0] = SCA_HEX, /* start */ | 665 | .arg_scnprintf = { [0] = SCA_HEX, /* start */ |
707 | [2] = SCA_MADV_BHV, /* behavior */ }, }, | 666 | [2] = SCA_MADV_BHV, /* behavior */ }, }, |
708 | { .name = "mkdir", .errmsg = true, | 667 | { .name = "mkdir", .errmsg = true, }, |
709 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
710 | { .name = "mkdirat", .errmsg = true, | 668 | { .name = "mkdirat", .errmsg = true, |
711 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ | 669 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, |
712 | [1] = SCA_FILENAME, /* pathname */ }, }, | 670 | { .name = "mknod", .errmsg = true, }, |
713 | { .name = "mknod", .errmsg = true, | ||
714 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
715 | { .name = "mknodat", .errmsg = true, | 671 | { .name = "mknodat", .errmsg = true, |
716 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ | 672 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, |
717 | [1] = SCA_FILENAME, /* filename */ }, }, | ||
718 | { .name = "mlock", .errmsg = true, | 673 | { .name = "mlock", .errmsg = true, |
719 | .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, | 674 | .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, |
720 | { .name = "mlockall", .errmsg = true, | 675 | { .name = "mlockall", .errmsg = true, |
@@ -722,8 +677,7 @@ static struct syscall_fmt { | |||
722 | { .name = "mmap", .hexret = true, | 677 | { .name = "mmap", .hexret = true, |
723 | .arg_scnprintf = { [0] = SCA_HEX, /* addr */ | 678 | .arg_scnprintf = { [0] = SCA_HEX, /* addr */ |
724 | [2] = SCA_MMAP_PROT, /* prot */ | 679 | [2] = SCA_MMAP_PROT, /* prot */ |
725 | [3] = SCA_MMAP_FLAGS, /* flags */ | 680 | [3] = SCA_MMAP_FLAGS, /* flags */ }, }, |
726 | [4] = SCA_FD, /* fd */ }, }, | ||
727 | { .name = "mprotect", .errmsg = true, | 681 | { .name = "mprotect", .errmsg = true, |
728 | .arg_scnprintf = { [0] = SCA_HEX, /* start */ | 682 | .arg_scnprintf = { [0] = SCA_HEX, /* start */ |
729 | [2] = SCA_MMAP_PROT, /* prot */ }, }, | 683 | [2] = SCA_MMAP_PROT, /* prot */ }, }, |
@@ -740,17 +694,14 @@ static struct syscall_fmt { | |||
740 | { .name = "name_to_handle_at", .errmsg = true, | 694 | { .name = "name_to_handle_at", .errmsg = true, |
741 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, | 695 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, |
742 | { .name = "newfstatat", .errmsg = true, | 696 | { .name = "newfstatat", .errmsg = true, |
743 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ | 697 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, |
744 | [1] = SCA_FILENAME, /* filename */ }, }, | ||
745 | { .name = "open", .errmsg = true, | 698 | { .name = "open", .errmsg = true, |
746 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ | 699 | .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, }, |
747 | [1] = SCA_OPEN_FLAGS, /* flags */ }, }, | ||
748 | { .name = "open_by_handle_at", .errmsg = true, | 700 | { .name = "open_by_handle_at", .errmsg = true, |
749 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ | 701 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ |
750 | [2] = SCA_OPEN_FLAGS, /* flags */ }, }, | 702 | [2] = SCA_OPEN_FLAGS, /* flags */ }, }, |
751 | { .name = "openat", .errmsg = true, | 703 | { .name = "openat", .errmsg = true, |
752 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ | 704 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ |
753 | [1] = SCA_FILENAME, /* filename */ | ||
754 | [2] = SCA_OPEN_FLAGS, /* flags */ }, }, | 705 | [2] = SCA_OPEN_FLAGS, /* flags */ }, }, |
755 | { .name = "perf_event_open", .errmsg = true, | 706 | { .name = "perf_event_open", .errmsg = true, |
756 | .arg_scnprintf = { [2] = SCA_INT, /* cpu */ | 707 | .arg_scnprintf = { [2] = SCA_INT, /* cpu */ |
@@ -760,39 +711,26 @@ static struct syscall_fmt { | |||
760 | .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, }, | 711 | .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, }, |
761 | { .name = "poll", .errmsg = true, .timeout = true, }, | 712 | { .name = "poll", .errmsg = true, .timeout = true, }, |
762 | { .name = "ppoll", .errmsg = true, .timeout = true, }, | 713 | { .name = "ppoll", .errmsg = true, .timeout = true, }, |
763 | { .name = "pread", .errmsg = true, .alias = "pread64", | 714 | { .name = "pread", .errmsg = true, .alias = "pread64", }, |
764 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 715 | { .name = "preadv", .errmsg = true, .alias = "pread", }, |
765 | { .name = "preadv", .errmsg = true, .alias = "pread", | ||
766 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
767 | { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), }, | 716 | { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), }, |
768 | { .name = "pwrite", .errmsg = true, .alias = "pwrite64", | 717 | { .name = "pwrite", .errmsg = true, .alias = "pwrite64", }, |
769 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 718 | { .name = "pwritev", .errmsg = true, }, |
770 | { .name = "pwritev", .errmsg = true, | 719 | { .name = "read", .errmsg = true, }, |
771 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 720 | { .name = "readlink", .errmsg = true, }, |
772 | { .name = "read", .errmsg = true, | ||
773 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
774 | { .name = "readlink", .errmsg = true, | ||
775 | .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, }, | ||
776 | { .name = "readlinkat", .errmsg = true, | 721 | { .name = "readlinkat", .errmsg = true, |
777 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ | 722 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, |
778 | [1] = SCA_FILENAME, /* pathname */ }, }, | 723 | { .name = "readv", .errmsg = true, }, |
779 | { .name = "readv", .errmsg = true, | ||
780 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
781 | { .name = "recvfrom", .errmsg = true, | 724 | { .name = "recvfrom", .errmsg = true, |
782 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 725 | .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, |
783 | [3] = SCA_MSG_FLAGS, /* flags */ }, }, | ||
784 | { .name = "recvmmsg", .errmsg = true, | 726 | { .name = "recvmmsg", .errmsg = true, |
785 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 727 | .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, |
786 | [3] = SCA_MSG_FLAGS, /* flags */ }, }, | ||
787 | { .name = "recvmsg", .errmsg = true, | 728 | { .name = "recvmsg", .errmsg = true, |
788 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 729 | .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, |
789 | [2] = SCA_MSG_FLAGS, /* flags */ }, }, | 730 | { .name = "removexattr", .errmsg = true, }, |
790 | { .name = "removexattr", .errmsg = true, | ||
791 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
792 | { .name = "renameat", .errmsg = true, | 731 | { .name = "renameat", .errmsg = true, |
793 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, | 732 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, |
794 | { .name = "rmdir", .errmsg = true, | 733 | { .name = "rmdir", .errmsg = true, }, |
795 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
796 | { .name = "rt_sigaction", .errmsg = true, | 734 | { .name = "rt_sigaction", .errmsg = true, |
797 | .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, }, | 735 | .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, }, |
798 | { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), }, | 736 | { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), }, |
@@ -807,22 +745,17 @@ static struct syscall_fmt { | |||
807 | [1] = SCA_SECCOMP_FLAGS, /* flags */ }, }, | 745 | [1] = SCA_SECCOMP_FLAGS, /* flags */ }, }, |
808 | { .name = "select", .errmsg = true, .timeout = true, }, | 746 | { .name = "select", .errmsg = true, .timeout = true, }, |
809 | { .name = "sendmmsg", .errmsg = true, | 747 | { .name = "sendmmsg", .errmsg = true, |
810 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 748 | .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, |
811 | [3] = SCA_MSG_FLAGS, /* flags */ }, }, | ||
812 | { .name = "sendmsg", .errmsg = true, | 749 | { .name = "sendmsg", .errmsg = true, |
813 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 750 | .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, |
814 | [2] = SCA_MSG_FLAGS, /* flags */ }, }, | ||
815 | { .name = "sendto", .errmsg = true, | 751 | { .name = "sendto", .errmsg = true, |
816 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 752 | .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, |
817 | [3] = SCA_MSG_FLAGS, /* flags */ }, }, | ||
818 | { .name = "set_tid_address", .errpid = true, }, | 753 | { .name = "set_tid_address", .errpid = true, }, |
819 | { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, | 754 | { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, |
820 | { .name = "setpgid", .errmsg = true, }, | 755 | { .name = "setpgid", .errmsg = true, }, |
821 | { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, | 756 | { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, |
822 | { .name = "setxattr", .errmsg = true, | 757 | { .name = "setxattr", .errmsg = true, }, |
823 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | 758 | { .name = "shutdown", .errmsg = true, }, |
824 | { .name = "shutdown", .errmsg = true, | ||
825 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
826 | { .name = "socket", .errmsg = true, | 759 | { .name = "socket", .errmsg = true, |
827 | .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ | 760 | .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ |
828 | [1] = SCA_SK_TYPE, /* type */ }, | 761 | [1] = SCA_SK_TYPE, /* type */ }, |
@@ -831,10 +764,8 @@ static struct syscall_fmt { | |||
831 | .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ | 764 | .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ |
832 | [1] = SCA_SK_TYPE, /* type */ }, | 765 | [1] = SCA_SK_TYPE, /* type */ }, |
833 | .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, | 766 | .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, |
834 | { .name = "stat", .errmsg = true, .alias = "newstat", | 767 | { .name = "stat", .errmsg = true, .alias = "newstat", }, |
835 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | 768 | { .name = "statfs", .errmsg = true, }, |
836 | { .name = "statfs", .errmsg = true, | ||
837 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
838 | { .name = "swapoff", .errmsg = true, | 769 | { .name = "swapoff", .errmsg = true, |
839 | .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, }, | 770 | .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, }, |
840 | { .name = "swapon", .errmsg = true, | 771 | { .name = "swapon", .errmsg = true, |
@@ -845,29 +776,21 @@ static struct syscall_fmt { | |||
845 | .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, | 776 | .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, |
846 | { .name = "tkill", .errmsg = true, | 777 | { .name = "tkill", .errmsg = true, |
847 | .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, | 778 | .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, |
848 | { .name = "truncate", .errmsg = true, | 779 | { .name = "truncate", .errmsg = true, }, |
849 | .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, }, | ||
850 | { .name = "uname", .errmsg = true, .alias = "newuname", }, | 780 | { .name = "uname", .errmsg = true, .alias = "newuname", }, |
851 | { .name = "unlinkat", .errmsg = true, | 781 | { .name = "unlinkat", .errmsg = true, |
852 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ | 782 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, |
853 | [1] = SCA_FILENAME, /* pathname */ }, }, | 783 | { .name = "utime", .errmsg = true, }, |
854 | { .name = "utime", .errmsg = true, | ||
855 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
856 | { .name = "utimensat", .errmsg = true, | 784 | { .name = "utimensat", .errmsg = true, |
857 | .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ | 785 | .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, }, |
858 | [1] = SCA_FILENAME, /* filename */ }, }, | 786 | { .name = "utimes", .errmsg = true, }, |
859 | { .name = "utimes", .errmsg = true, | 787 | { .name = "vmsplice", .errmsg = true, }, |
860 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
861 | { .name = "vmsplice", .errmsg = true, | ||
862 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
863 | { .name = "wait4", .errpid = true, | 788 | { .name = "wait4", .errpid = true, |
864 | .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, }, | 789 | .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, }, |
865 | { .name = "waitid", .errpid = true, | 790 | { .name = "waitid", .errpid = true, |
866 | .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, }, | 791 | .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, }, |
867 | { .name = "write", .errmsg = true, | 792 | { .name = "write", .errmsg = true, }, |
868 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 793 | { .name = "writev", .errmsg = true, }, |
869 | { .name = "writev", .errmsg = true, | ||
870 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
871 | }; | 794 | }; |
872 | 795 | ||
873 | static int syscall_fmt__cmp(const void *name, const void *fmtp) | 796 | static int syscall_fmt__cmp(const void *name, const void *fmtp) |
@@ -1160,6 +1083,24 @@ static int trace__tool_process(struct perf_tool *tool, | |||
1160 | return trace__process_event(trace, machine, event, sample); | 1083 | return trace__process_event(trace, machine, event, sample); |
1161 | } | 1084 | } |
1162 | 1085 | ||
1086 | static char *trace__machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, char **modp) | ||
1087 | { | ||
1088 | struct machine *machine = vmachine; | ||
1089 | |||
1090 | if (machine->kptr_restrict_warned) | ||
1091 | return NULL; | ||
1092 | |||
1093 | if (symbol_conf.kptr_restrict) { | ||
1094 | pr_warning("Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n" | ||
1095 | "Check /proc/sys/kernel/kptr_restrict.\n\n" | ||
1096 | "Kernel samples will not be resolved.\n"); | ||
1097 | machine->kptr_restrict_warned = true; | ||
1098 | return NULL; | ||
1099 | } | ||
1100 | |||
1101 | return machine__resolve_kernel_addr(vmachine, addrp, modp); | ||
1102 | } | ||
1103 | |||
1163 | static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) | 1104 | static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) |
1164 | { | 1105 | { |
1165 | int err = symbol__init(NULL); | 1106 | int err = symbol__init(NULL); |
@@ -1171,7 +1112,7 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) | |||
1171 | if (trace->host == NULL) | 1112 | if (trace->host == NULL) |
1172 | return -ENOMEM; | 1113 | return -ENOMEM; |
1173 | 1114 | ||
1174 | if (trace_event__register_resolver(trace->host, machine__resolve_kernel_addr) < 0) | 1115 | if (trace_event__register_resolver(trace->host, trace__machine__resolve_kernel_addr) < 0) |
1175 | return -errno; | 1116 | return -errno; |
1176 | 1117 | ||
1177 | err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target, | 1118 | err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target, |
@@ -1186,7 +1127,7 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) | |||
1186 | static int syscall__set_arg_fmts(struct syscall *sc) | 1127 | static int syscall__set_arg_fmts(struct syscall *sc) |
1187 | { | 1128 | { |
1188 | struct format_field *field; | 1129 | struct format_field *field; |
1189 | int idx = 0; | 1130 | int idx = 0, len; |
1190 | 1131 | ||
1191 | sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *)); | 1132 | sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *)); |
1192 | if (sc->arg_scnprintf == NULL) | 1133 | if (sc->arg_scnprintf == NULL) |
@@ -1198,12 +1139,31 @@ static int syscall__set_arg_fmts(struct syscall *sc) | |||
1198 | for (field = sc->args; field; field = field->next) { | 1139 | for (field = sc->args; field; field = field->next) { |
1199 | if (sc->fmt && sc->fmt->arg_scnprintf[idx]) | 1140 | if (sc->fmt && sc->fmt->arg_scnprintf[idx]) |
1200 | sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx]; | 1141 | sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx]; |
1142 | else if (strcmp(field->type, "const char *") == 0 && | ||
1143 | (strcmp(field->name, "filename") == 0 || | ||
1144 | strcmp(field->name, "path") == 0 || | ||
1145 | strcmp(field->name, "pathname") == 0)) | ||
1146 | sc->arg_scnprintf[idx] = SCA_FILENAME; | ||
1201 | else if (field->flags & FIELD_IS_POINTER) | 1147 | else if (field->flags & FIELD_IS_POINTER) |
1202 | sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex; | 1148 | sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex; |
1203 | else if (strcmp(field->type, "pid_t") == 0) | 1149 | else if (strcmp(field->type, "pid_t") == 0) |
1204 | sc->arg_scnprintf[idx] = SCA_PID; | 1150 | sc->arg_scnprintf[idx] = SCA_PID; |
1205 | else if (strcmp(field->type, "umode_t") == 0) | 1151 | else if (strcmp(field->type, "umode_t") == 0) |
1206 | sc->arg_scnprintf[idx] = SCA_MODE_T; | 1152 | sc->arg_scnprintf[idx] = SCA_MODE_T; |
1153 | else if ((strcmp(field->type, "int") == 0 || | ||
1154 | strcmp(field->type, "unsigned int") == 0 || | ||
1155 | strcmp(field->type, "long") == 0) && | ||
1156 | (len = strlen(field->name)) >= 2 && | ||
1157 | strcmp(field->name + len - 2, "fd") == 0) { | ||
1158 | /* | ||
1159 | * /sys/kernel/tracing/events/syscalls/sys_enter* | ||
1160 | * egrep 'field:.*fd;' .../format|sed -r 's/.*field:([a-z ]+) [a-z_]*fd.+/\1/g'|sort|uniq -c | ||
1161 | * 65 int | ||
1162 | * 23 unsigned int | ||
1163 | * 7 unsigned long | ||
1164 | */ | ||
1165 | sc->arg_scnprintf[idx] = SCA_FD; | ||
1166 | } | ||
1207 | ++idx; | 1167 | ++idx; |
1208 | } | 1168 | } |
1209 | 1169 | ||
@@ -1534,7 +1494,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, | |||
1534 | if (sc->is_exit) { | 1494 | if (sc->is_exit) { |
1535 | if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) { | 1495 | if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) { |
1536 | trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output); | 1496 | trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output); |
1537 | fprintf(trace->output, "%-70s\n", ttrace->entry_str); | 1497 | fprintf(trace->output, "%-70s)\n", ttrace->entry_str); |
1538 | } | 1498 | } |
1539 | } else { | 1499 | } else { |
1540 | ttrace->entry_pending = true; | 1500 | ttrace->entry_pending = true; |
@@ -2887,12 +2847,12 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) | |||
2887 | mmap_pages_user_set = false; | 2847 | mmap_pages_user_set = false; |
2888 | 2848 | ||
2889 | if (trace.max_stack == UINT_MAX) { | 2849 | if (trace.max_stack == UINT_MAX) { |
2890 | trace.max_stack = sysctl_perf_event_max_stack; | 2850 | trace.max_stack = input_name ? PERF_MAX_STACK_DEPTH : sysctl_perf_event_max_stack; |
2891 | max_stack_user_set = false; | 2851 | max_stack_user_set = false; |
2892 | } | 2852 | } |
2893 | 2853 | ||
2894 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | 2854 | #ifdef HAVE_DWARF_UNWIND_SUPPORT |
2895 | if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled) | 2855 | if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled && trace.trace_syscalls) |
2896 | record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false); | 2856 | record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false); |
2897 | #endif | 2857 | #endif |
2898 | 2858 | ||
diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 797000842d40..15982cee5ef3 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c | |||
@@ -549,6 +549,9 @@ int main(int argc, const char **argv) | |||
549 | if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0) | 549 | if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0) |
550 | sysctl_perf_event_max_stack = value; | 550 | sysctl_perf_event_max_stack = value; |
551 | 551 | ||
552 | if (sysctl__read_int("kernel/perf_event_max_contexts_per_stack", &value) == 0) | ||
553 | sysctl_perf_event_max_contexts_per_stack = value; | ||
554 | |||
552 | cmd = extract_argv0_path(argv[0]); | 555 | cmd = extract_argv0_path(argv[0]); |
553 | if (!cmd) | 556 | if (!cmd) |
554 | cmd = "perf-help"; | 557 | cmd = "perf-help"; |
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 4db73d5a0dbc..7e5a1e8874ce 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
@@ -354,9 +354,6 @@ static struct ins_ops nop_ops = { | |||
354 | .scnprintf = nop__scnprintf, | 354 | .scnprintf = nop__scnprintf, |
355 | }; | 355 | }; |
356 | 356 | ||
357 | /* | ||
358 | * Must be sorted by name! | ||
359 | */ | ||
360 | static struct ins instructions[] = { | 357 | static struct ins instructions[] = { |
361 | { .name = "add", .ops = &mov_ops, }, | 358 | { .name = "add", .ops = &mov_ops, }, |
362 | { .name = "addl", .ops = &mov_ops, }, | 359 | { .name = "addl", .ops = &mov_ops, }, |
@@ -372,8 +369,8 @@ static struct ins instructions[] = { | |||
372 | { .name = "bgt", .ops = &jump_ops, }, | 369 | { .name = "bgt", .ops = &jump_ops, }, |
373 | { .name = "bhi", .ops = &jump_ops, }, | 370 | { .name = "bhi", .ops = &jump_ops, }, |
374 | { .name = "bl", .ops = &call_ops, }, | 371 | { .name = "bl", .ops = &call_ops, }, |
375 | { .name = "blt", .ops = &jump_ops, }, | ||
376 | { .name = "bls", .ops = &jump_ops, }, | 372 | { .name = "bls", .ops = &jump_ops, }, |
373 | { .name = "blt", .ops = &jump_ops, }, | ||
377 | { .name = "blx", .ops = &call_ops, }, | 374 | { .name = "blx", .ops = &call_ops, }, |
378 | { .name = "bne", .ops = &jump_ops, }, | 375 | { .name = "bne", .ops = &jump_ops, }, |
379 | #endif | 376 | #endif |
@@ -449,18 +446,39 @@ static struct ins instructions[] = { | |||
449 | { .name = "xbeginq", .ops = &jump_ops, }, | 446 | { .name = "xbeginq", .ops = &jump_ops, }, |
450 | }; | 447 | }; |
451 | 448 | ||
452 | static int ins__cmp(const void *name, const void *insp) | 449 | static int ins__key_cmp(const void *name, const void *insp) |
453 | { | 450 | { |
454 | const struct ins *ins = insp; | 451 | const struct ins *ins = insp; |
455 | 452 | ||
456 | return strcmp(name, ins->name); | 453 | return strcmp(name, ins->name); |
457 | } | 454 | } |
458 | 455 | ||
456 | static int ins__cmp(const void *a, const void *b) | ||
457 | { | ||
458 | const struct ins *ia = a; | ||
459 | const struct ins *ib = b; | ||
460 | |||
461 | return strcmp(ia->name, ib->name); | ||
462 | } | ||
463 | |||
464 | static void ins__sort(void) | ||
465 | { | ||
466 | const int nmemb = ARRAY_SIZE(instructions); | ||
467 | |||
468 | qsort(instructions, nmemb, sizeof(struct ins), ins__cmp); | ||
469 | } | ||
470 | |||
459 | static struct ins *ins__find(const char *name) | 471 | static struct ins *ins__find(const char *name) |
460 | { | 472 | { |
461 | const int nmemb = ARRAY_SIZE(instructions); | 473 | const int nmemb = ARRAY_SIZE(instructions); |
474 | static bool sorted; | ||
475 | |||
476 | if (!sorted) { | ||
477 | ins__sort(); | ||
478 | sorted = true; | ||
479 | } | ||
462 | 480 | ||
463 | return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__cmp); | 481 | return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__key_cmp); |
464 | } | 482 | } |
465 | 483 | ||
466 | int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym) | 484 | int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym) |
@@ -1122,7 +1140,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) | |||
1122 | } else if (dso__is_kcore(dso)) { | 1140 | } else if (dso__is_kcore(dso)) { |
1123 | goto fallback; | 1141 | goto fallback; |
1124 | } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || | 1142 | } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || |
1125 | strstr(command, "[kernel.kallsyms]") || | 1143 | strstr(command, DSO__NAME_KALLSYMS) || |
1126 | access(symfs_filename, R_OK)) { | 1144 | access(symfs_filename, R_OK)) { |
1127 | free(filename); | 1145 | free(filename); |
1128 | fallback: | 1146 | fallback: |
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index bff425e1232c..67e5966503b2 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
@@ -256,7 +256,7 @@ static int machine__write_buildid_table(struct machine *machine, int fd) | |||
256 | size_t name_len; | 256 | size_t name_len; |
257 | bool in_kernel = false; | 257 | bool in_kernel = false; |
258 | 258 | ||
259 | if (!pos->hit) | 259 | if (!pos->hit && !dso__is_vdso(pos)) |
260 | continue; | 260 | continue; |
261 | 261 | ||
262 | if (dso__is_vdso(pos)) { | 262 | if (dso__is_vdso(pos)) { |
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index bbf69d248ec5..9f53020c3269 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c | |||
@@ -204,6 +204,44 @@ static unsigned long long adjust_signedness(unsigned long long value_int, int si | |||
204 | return (value_int & value_mask) | ~value_mask; | 204 | return (value_int & value_mask) | ~value_mask; |
205 | } | 205 | } |
206 | 206 | ||
207 | static int string_set_value(struct bt_ctf_field *field, const char *string) | ||
208 | { | ||
209 | char *buffer = NULL; | ||
210 | size_t len = strlen(string), i, p; | ||
211 | int err; | ||
212 | |||
213 | for (i = p = 0; i < len; i++, p++) { | ||
214 | if (isprint(string[i])) { | ||
215 | if (!buffer) | ||
216 | continue; | ||
217 | buffer[p] = string[i]; | ||
218 | } else { | ||
219 | char numstr[5]; | ||
220 | |||
221 | snprintf(numstr, sizeof(numstr), "\\x%02x", | ||
222 | (unsigned int)(string[i]) & 0xff); | ||
223 | |||
224 | if (!buffer) { | ||
225 | buffer = zalloc(i + (len - i) * 4 + 2); | ||
226 | if (!buffer) { | ||
227 | pr_err("failed to set unprintable string '%s'\n", string); | ||
228 | return bt_ctf_field_string_set_value(field, "UNPRINTABLE-STRING"); | ||
229 | } | ||
230 | if (i > 0) | ||
231 | strncpy(buffer, string, i); | ||
232 | } | ||
233 | strncat(buffer + p, numstr, 4); | ||
234 | p += 3; | ||
235 | } | ||
236 | } | ||
237 | |||
238 | if (!buffer) | ||
239 | return bt_ctf_field_string_set_value(field, string); | ||
240 | err = bt_ctf_field_string_set_value(field, buffer); | ||
241 | free(buffer); | ||
242 | return err; | ||
243 | } | ||
244 | |||
207 | static int add_tracepoint_field_value(struct ctf_writer *cw, | 245 | static int add_tracepoint_field_value(struct ctf_writer *cw, |
208 | struct bt_ctf_event_class *event_class, | 246 | struct bt_ctf_event_class *event_class, |
209 | struct bt_ctf_event *event, | 247 | struct bt_ctf_event *event, |
@@ -270,8 +308,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw, | |||
270 | } | 308 | } |
271 | 309 | ||
272 | if (flags & FIELD_IS_STRING) | 310 | if (flags & FIELD_IS_STRING) |
273 | ret = bt_ctf_field_string_set_value(field, | 311 | ret = string_set_value(field, data + offset + i * len); |
274 | data + offset + i * len); | ||
275 | else { | 312 | else { |
276 | unsigned long long value_int; | 313 | unsigned long long value_int; |
277 | 314 | ||
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c index 8d96c80cc67e..c9a6dc173e74 100644 --- a/tools/perf/util/db-export.c +++ b/tools/perf/util/db-export.c | |||
@@ -298,8 +298,7 @@ static struct call_path *call_path_from_sample(struct db_export *dbe, | |||
298 | */ | 298 | */ |
299 | callchain_param.order = ORDER_CALLER; | 299 | callchain_param.order = ORDER_CALLER; |
300 | err = thread__resolve_callchain(thread, &callchain_cursor, evsel, | 300 | err = thread__resolve_callchain(thread, &callchain_cursor, evsel, |
301 | sample, NULL, NULL, | 301 | sample, NULL, NULL, PERF_MAX_STACK_DEPTH); |
302 | sysctl_perf_event_max_stack); | ||
303 | if (err) { | 302 | if (err) { |
304 | callchain_param.order = saved_order; | 303 | callchain_param.order = saved_order; |
305 | return NULL; | 304 | return NULL; |
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 3357479082ca..5d286f5d7906 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include "auxtrace.h" | 7 | #include "auxtrace.h" |
8 | #include "util.h" | 8 | #include "util.h" |
9 | #include "debug.h" | 9 | #include "debug.h" |
10 | #include "vdso.h" | ||
10 | 11 | ||
11 | char dso__symtab_origin(const struct dso *dso) | 12 | char dso__symtab_origin(const struct dso *dso) |
12 | { | 13 | { |
@@ -62,9 +63,7 @@ int dso__read_binary_type_filename(const struct dso *dso, | |||
62 | } | 63 | } |
63 | break; | 64 | break; |
64 | case DSO_BINARY_TYPE__BUILD_ID_CACHE: | 65 | case DSO_BINARY_TYPE__BUILD_ID_CACHE: |
65 | /* skip the locally configured cache if a symfs is given */ | 66 | if (dso__build_id_filename(dso, filename, size) == NULL) |
66 | if (symbol_conf.symfs[0] || | ||
67 | (dso__build_id_filename(dso, filename, size) == NULL)) | ||
68 | ret = -1; | 67 | ret = -1; |
69 | break; | 68 | break; |
70 | 69 | ||
@@ -1169,7 +1168,7 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits) | |||
1169 | struct dso *pos; | 1168 | struct dso *pos; |
1170 | 1169 | ||
1171 | list_for_each_entry(pos, head, node) { | 1170 | list_for_each_entry(pos, head, node) { |
1172 | if (with_hits && !pos->hit) | 1171 | if (with_hits && !pos->hit && !dso__is_vdso(pos)) |
1173 | continue; | 1172 | continue; |
1174 | if (pos->has_build_id) { | 1173 | if (pos->has_build_id) { |
1175 | have_build_id = true; | 1174 | have_build_id = true; |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index f6fcc6832949..9b141f12329e 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -673,6 +673,8 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, | |||
673 | int err; | 673 | int err; |
674 | union perf_event *event; | 674 | union perf_event *event; |
675 | 675 | ||
676 | if (symbol_conf.kptr_restrict) | ||
677 | return -1; | ||
676 | if (map == NULL) | 678 | if (map == NULL) |
677 | return -1; | 679 | return -1; |
678 | 680 | ||
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index c4bfe11479a0..e82ba90cc969 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -44,6 +44,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, | |||
44 | perf_evlist__set_maps(evlist, cpus, threads); | 44 | perf_evlist__set_maps(evlist, cpus, threads); |
45 | fdarray__init(&evlist->pollfd, 64); | 45 | fdarray__init(&evlist->pollfd, 64); |
46 | evlist->workload.pid = -1; | 46 | evlist->workload.pid = -1; |
47 | evlist->backward = false; | ||
47 | } | 48 | } |
48 | 49 | ||
49 | struct perf_evlist *perf_evlist__new(void) | 50 | struct perf_evlist *perf_evlist__new(void) |
@@ -679,6 +680,33 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, | |||
679 | return NULL; | 680 | return NULL; |
680 | } | 681 | } |
681 | 682 | ||
683 | static int perf_evlist__set_paused(struct perf_evlist *evlist, bool value) | ||
684 | { | ||
685 | int i; | ||
686 | |||
687 | for (i = 0; i < evlist->nr_mmaps; i++) { | ||
688 | int fd = evlist->mmap[i].fd; | ||
689 | int err; | ||
690 | |||
691 | if (fd < 0) | ||
692 | continue; | ||
693 | err = ioctl(fd, PERF_EVENT_IOC_PAUSE_OUTPUT, value ? 1 : 0); | ||
694 | if (err) | ||
695 | return err; | ||
696 | } | ||
697 | return 0; | ||
698 | } | ||
699 | |||
700 | int perf_evlist__pause(struct perf_evlist *evlist) | ||
701 | { | ||
702 | return perf_evlist__set_paused(evlist, true); | ||
703 | } | ||
704 | |||
705 | int perf_evlist__resume(struct perf_evlist *evlist) | ||
706 | { | ||
707 | return perf_evlist__set_paused(evlist, false); | ||
708 | } | ||
709 | |||
682 | /* When check_messup is true, 'end' must points to a good entry */ | 710 | /* When check_messup is true, 'end' must points to a good entry */ |
683 | static union perf_event * | 711 | static union perf_event * |
684 | perf_mmap__read(struct perf_mmap *md, bool check_messup, u64 start, | 712 | perf_mmap__read(struct perf_mmap *md, bool check_messup, u64 start, |
@@ -881,6 +909,7 @@ static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) | |||
881 | if (evlist->mmap[idx].base != NULL) { | 909 | if (evlist->mmap[idx].base != NULL) { |
882 | munmap(evlist->mmap[idx].base, evlist->mmap_len); | 910 | munmap(evlist->mmap[idx].base, evlist->mmap_len); |
883 | evlist->mmap[idx].base = NULL; | 911 | evlist->mmap[idx].base = NULL; |
912 | evlist->mmap[idx].fd = -1; | ||
884 | atomic_set(&evlist->mmap[idx].refcnt, 0); | 913 | atomic_set(&evlist->mmap[idx].refcnt, 0); |
885 | } | 914 | } |
886 | auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap); | 915 | auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap); |
@@ -901,10 +930,14 @@ void perf_evlist__munmap(struct perf_evlist *evlist) | |||
901 | 930 | ||
902 | static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) | 931 | static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) |
903 | { | 932 | { |
933 | int i; | ||
934 | |||
904 | evlist->nr_mmaps = cpu_map__nr(evlist->cpus); | 935 | evlist->nr_mmaps = cpu_map__nr(evlist->cpus); |
905 | if (cpu_map__empty(evlist->cpus)) | 936 | if (cpu_map__empty(evlist->cpus)) |
906 | evlist->nr_mmaps = thread_map__nr(evlist->threads); | 937 | evlist->nr_mmaps = thread_map__nr(evlist->threads); |
907 | evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); | 938 | evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); |
939 | for (i = 0; i < evlist->nr_mmaps; i++) | ||
940 | evlist->mmap[i].fd = -1; | ||
908 | return evlist->mmap != NULL ? 0 : -ENOMEM; | 941 | return evlist->mmap != NULL ? 0 : -ENOMEM; |
909 | } | 942 | } |
910 | 943 | ||
@@ -941,6 +974,7 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, | |||
941 | evlist->mmap[idx].base = NULL; | 974 | evlist->mmap[idx].base = NULL; |
942 | return -1; | 975 | return -1; |
943 | } | 976 | } |
977 | evlist->mmap[idx].fd = fd; | ||
944 | 978 | ||
945 | if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap, | 979 | if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap, |
946 | &mp->auxtrace_mp, evlist->mmap[idx].base, fd)) | 980 | &mp->auxtrace_mp, evlist->mmap[idx].base, fd)) |
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 85d1b59802e8..d740fb877ab6 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
@@ -28,6 +28,7 @@ struct record_opts; | |||
28 | struct perf_mmap { | 28 | struct perf_mmap { |
29 | void *base; | 29 | void *base; |
30 | int mask; | 30 | int mask; |
31 | int fd; | ||
31 | atomic_t refcnt; | 32 | atomic_t refcnt; |
32 | u64 prev; | 33 | u64 prev; |
33 | struct auxtrace_mmap auxtrace_mmap; | 34 | struct auxtrace_mmap auxtrace_mmap; |
@@ -43,6 +44,7 @@ struct perf_evlist { | |||
43 | bool overwrite; | 44 | bool overwrite; |
44 | bool enabled; | 45 | bool enabled; |
45 | bool has_user_cpus; | 46 | bool has_user_cpus; |
47 | bool backward; | ||
46 | size_t mmap_len; | 48 | size_t mmap_len; |
47 | int id_pos; | 49 | int id_pos; |
48 | int is_pos; | 50 | int is_pos; |
@@ -135,6 +137,8 @@ void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx); | |||
135 | 137 | ||
136 | void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); | 138 | void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); |
137 | 139 | ||
140 | int perf_evlist__pause(struct perf_evlist *evlist); | ||
141 | int perf_evlist__resume(struct perf_evlist *evlist); | ||
138 | int perf_evlist__open(struct perf_evlist *evlist); | 142 | int perf_evlist__open(struct perf_evlist *evlist); |
139 | void perf_evlist__close(struct perf_evlist *evlist); | 143 | void perf_evlist__close(struct perf_evlist *evlist); |
140 | 144 | ||
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 52c7d8884741..5d7037ef7d3b 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -37,6 +37,7 @@ static struct { | |||
37 | bool clockid; | 37 | bool clockid; |
38 | bool clockid_wrong; | 38 | bool clockid_wrong; |
39 | bool lbr_flags; | 39 | bool lbr_flags; |
40 | bool write_backward; | ||
40 | } perf_missing_features; | 41 | } perf_missing_features; |
41 | 42 | ||
42 | static clockid_t clockid; | 43 | static clockid_t clockid; |
@@ -1376,6 +1377,8 @@ fallback_missing_features: | |||
1376 | if (perf_missing_features.lbr_flags) | 1377 | if (perf_missing_features.lbr_flags) |
1377 | evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | | 1378 | evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | |
1378 | PERF_SAMPLE_BRANCH_NO_CYCLES); | 1379 | PERF_SAMPLE_BRANCH_NO_CYCLES); |
1380 | if (perf_missing_features.write_backward) | ||
1381 | evsel->attr.write_backward = false; | ||
1379 | retry_sample_id: | 1382 | retry_sample_id: |
1380 | if (perf_missing_features.sample_id_all) | 1383 | if (perf_missing_features.sample_id_all) |
1381 | evsel->attr.sample_id_all = 0; | 1384 | evsel->attr.sample_id_all = 0; |
@@ -1438,6 +1441,12 @@ retry_open: | |||
1438 | err = -EINVAL; | 1441 | err = -EINVAL; |
1439 | goto out_close; | 1442 | goto out_close; |
1440 | } | 1443 | } |
1444 | |||
1445 | if (evsel->overwrite && | ||
1446 | perf_missing_features.write_backward) { | ||
1447 | err = -EINVAL; | ||
1448 | goto out_close; | ||
1449 | } | ||
1441 | } | 1450 | } |
1442 | } | 1451 | } |
1443 | 1452 | ||
@@ -1500,6 +1509,10 @@ try_fallback: | |||
1500 | PERF_SAMPLE_BRANCH_NO_FLAGS))) { | 1509 | PERF_SAMPLE_BRANCH_NO_FLAGS))) { |
1501 | perf_missing_features.lbr_flags = true; | 1510 | perf_missing_features.lbr_flags = true; |
1502 | goto fallback_missing_features; | 1511 | goto fallback_missing_features; |
1512 | } else if (!perf_missing_features.write_backward && | ||
1513 | evsel->attr.write_backward) { | ||
1514 | perf_missing_features.write_backward = true; | ||
1515 | goto fallback_missing_features; | ||
1503 | } | 1516 | } |
1504 | 1517 | ||
1505 | out_close: | 1518 | out_close: |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 8a644fef452c..c1f10159804c 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -112,6 +112,7 @@ struct perf_evsel { | |||
112 | bool tracking; | 112 | bool tracking; |
113 | bool per_pkg; | 113 | bool per_pkg; |
114 | bool precise_max; | 114 | bool precise_max; |
115 | bool overwrite; | ||
115 | /* parse modifier helper */ | 116 | /* parse modifier helper */ |
116 | int exclude_GH; | 117 | int exclude_GH; |
117 | int nr_members; | 118 | int nr_members; |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index cfab531437c7..d1f19e0012d4 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -117,6 +117,13 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) | |||
117 | hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen); | 117 | hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen); |
118 | hists__set_unres_dso_col_len(hists, HISTC_DSO_TO); | 118 | hists__set_unres_dso_col_len(hists, HISTC_DSO_TO); |
119 | } | 119 | } |
120 | |||
121 | if (h->branch_info->srcline_from) | ||
122 | hists__new_col_len(hists, HISTC_SRCLINE_FROM, | ||
123 | strlen(h->branch_info->srcline_from)); | ||
124 | if (h->branch_info->srcline_to) | ||
125 | hists__new_col_len(hists, HISTC_SRCLINE_TO, | ||
126 | strlen(h->branch_info->srcline_to)); | ||
120 | } | 127 | } |
121 | 128 | ||
122 | if (h->mem_info) { | 129 | if (h->mem_info) { |
@@ -1042,6 +1049,8 @@ void hist_entry__delete(struct hist_entry *he) | |||
1042 | if (he->branch_info) { | 1049 | if (he->branch_info) { |
1043 | map__zput(he->branch_info->from.map); | 1050 | map__zput(he->branch_info->from.map); |
1044 | map__zput(he->branch_info->to.map); | 1051 | map__zput(he->branch_info->to.map); |
1052 | free_srcline(he->branch_info->srcline_from); | ||
1053 | free_srcline(he->branch_info->srcline_to); | ||
1045 | zfree(&he->branch_info); | 1054 | zfree(&he->branch_info); |
1046 | } | 1055 | } |
1047 | 1056 | ||
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 0f84bfb42bb1..7b54ccf1b737 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -52,6 +52,8 @@ enum hist_column { | |||
52 | HISTC_MEM_IADDR_SYMBOL, | 52 | HISTC_MEM_IADDR_SYMBOL, |
53 | HISTC_TRANSACTION, | 53 | HISTC_TRANSACTION, |
54 | HISTC_CYCLES, | 54 | HISTC_CYCLES, |
55 | HISTC_SRCLINE_FROM, | ||
56 | HISTC_SRCLINE_TO, | ||
55 | HISTC_TRACE, | 57 | HISTC_TRACE, |
56 | HISTC_NR_COLS, /* Last entry */ | 58 | HISTC_NR_COLS, /* Last entry */ |
57 | }; | 59 | }; |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index f9644f79686c..b1772180c820 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -43,6 +43,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid) | |||
43 | 43 | ||
44 | machine->symbol_filter = NULL; | 44 | machine->symbol_filter = NULL; |
45 | machine->id_hdr_size = 0; | 45 | machine->id_hdr_size = 0; |
46 | machine->kptr_restrict_warned = false; | ||
46 | machine->comm_exec = false; | 47 | machine->comm_exec = false; |
47 | machine->kernel_start = 0; | 48 | machine->kernel_start = 0; |
48 | 49 | ||
@@ -709,7 +710,7 @@ static struct dso *machine__get_kernel(struct machine *machine) | |||
709 | if (machine__is_host(machine)) { | 710 | if (machine__is_host(machine)) { |
710 | vmlinux_name = symbol_conf.vmlinux_name; | 711 | vmlinux_name = symbol_conf.vmlinux_name; |
711 | if (!vmlinux_name) | 712 | if (!vmlinux_name) |
712 | vmlinux_name = "[kernel.kallsyms]"; | 713 | vmlinux_name = DSO__NAME_KALLSYMS; |
713 | 714 | ||
714 | kernel = machine__findnew_kernel(machine, vmlinux_name, | 715 | kernel = machine__findnew_kernel(machine, vmlinux_name, |
715 | "[kernel]", DSO_TYPE_KERNEL); | 716 | "[kernel]", DSO_TYPE_KERNEL); |
@@ -1135,10 +1136,10 @@ int machine__create_kernel_maps(struct machine *machine) | |||
1135 | { | 1136 | { |
1136 | struct dso *kernel = machine__get_kernel(machine); | 1137 | struct dso *kernel = machine__get_kernel(machine); |
1137 | const char *name; | 1138 | const char *name; |
1138 | u64 addr = machine__get_running_kernel_start(machine, &name); | 1139 | u64 addr; |
1139 | int ret; | 1140 | int ret; |
1140 | 1141 | ||
1141 | if (!addr || kernel == NULL) | 1142 | if (kernel == NULL) |
1142 | return -1; | 1143 | return -1; |
1143 | 1144 | ||
1144 | ret = __machine__create_kernel_maps(machine, kernel); | 1145 | ret = __machine__create_kernel_maps(machine, kernel); |
@@ -1160,8 +1161,9 @@ int machine__create_kernel_maps(struct machine *machine) | |||
1160 | */ | 1161 | */ |
1161 | map_groups__fixup_end(&machine->kmaps); | 1162 | map_groups__fixup_end(&machine->kmaps); |
1162 | 1163 | ||
1163 | if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, | 1164 | addr = machine__get_running_kernel_start(machine, &name); |
1164 | addr)) { | 1165 | if (!addr) { |
1166 | } else if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) { | ||
1165 | machine__destroy_kernel_maps(machine); | 1167 | machine__destroy_kernel_maps(machine); |
1166 | return -1; | 1168 | return -1; |
1167 | } | 1169 | } |
@@ -1769,11 +1771,6 @@ static int resolve_lbr_callchain_sample(struct thread *thread, | |||
1769 | */ | 1771 | */ |
1770 | int mix_chain_nr = i + 1 + lbr_nr + 1; | 1772 | int mix_chain_nr = i + 1 + lbr_nr + 1; |
1771 | 1773 | ||
1772 | if (mix_chain_nr > (int)sysctl_perf_event_max_stack + PERF_MAX_BRANCH_DEPTH) { | ||
1773 | pr_warning("corrupted callchain. skipping...\n"); | ||
1774 | return 0; | ||
1775 | } | ||
1776 | |||
1777 | for (j = 0; j < mix_chain_nr; j++) { | 1774 | for (j = 0; j < mix_chain_nr; j++) { |
1778 | if (callchain_param.order == ORDER_CALLEE) { | 1775 | if (callchain_param.order == ORDER_CALLEE) { |
1779 | if (j < i + 1) | 1776 | if (j < i + 1) |
@@ -1811,9 +1808,9 @@ static int thread__resolve_callchain_sample(struct thread *thread, | |||
1811 | { | 1808 | { |
1812 | struct branch_stack *branch = sample->branch_stack; | 1809 | struct branch_stack *branch = sample->branch_stack; |
1813 | struct ip_callchain *chain = sample->callchain; | 1810 | struct ip_callchain *chain = sample->callchain; |
1814 | int chain_nr = min(max_stack, (int)chain->nr); | 1811 | int chain_nr = chain->nr; |
1815 | u8 cpumode = PERF_RECORD_MISC_USER; | 1812 | u8 cpumode = PERF_RECORD_MISC_USER; |
1816 | int i, j, err; | 1813 | int i, j, err, nr_entries; |
1817 | int skip_idx = -1; | 1814 | int skip_idx = -1; |
1818 | int first_call = 0; | 1815 | int first_call = 0; |
1819 | 1816 | ||
@@ -1828,8 +1825,7 @@ static int thread__resolve_callchain_sample(struct thread *thread, | |||
1828 | * Based on DWARF debug information, some architectures skip | 1825 | * Based on DWARF debug information, some architectures skip |
1829 | * a callchain entry saved by the kernel. | 1826 | * a callchain entry saved by the kernel. |
1830 | */ | 1827 | */ |
1831 | if (chain->nr < sysctl_perf_event_max_stack) | 1828 | skip_idx = arch_skip_callchain_idx(thread, chain); |
1832 | skip_idx = arch_skip_callchain_idx(thread, chain); | ||
1833 | 1829 | ||
1834 | /* | 1830 | /* |
1835 | * Add branches to call stack for easier browsing. This gives | 1831 | * Add branches to call stack for easier browsing. This gives |
@@ -1889,12 +1885,8 @@ static int thread__resolve_callchain_sample(struct thread *thread, | |||
1889 | } | 1885 | } |
1890 | 1886 | ||
1891 | check_calls: | 1887 | check_calls: |
1892 | if (chain->nr > sysctl_perf_event_max_stack && (int)chain->nr > max_stack) { | 1888 | for (i = first_call, nr_entries = 0; |
1893 | pr_warning("corrupted callchain. skipping...\n"); | 1889 | i < chain_nr && nr_entries < max_stack; i++) { |
1894 | return 0; | ||
1895 | } | ||
1896 | |||
1897 | for (i = first_call; i < chain_nr; i++) { | ||
1898 | u64 ip; | 1890 | u64 ip; |
1899 | 1891 | ||
1900 | if (callchain_param.order == ORDER_CALLEE) | 1892 | if (callchain_param.order == ORDER_CALLEE) |
@@ -1908,6 +1900,9 @@ check_calls: | |||
1908 | #endif | 1900 | #endif |
1909 | ip = chain->ips[j]; | 1901 | ip = chain->ips[j]; |
1910 | 1902 | ||
1903 | if (ip < PERF_CONTEXT_MAX) | ||
1904 | ++nr_entries; | ||
1905 | |||
1911 | err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip); | 1906 | err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip); |
1912 | 1907 | ||
1913 | if (err) | 1908 | if (err) |
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 83f46790c52f..41ac9cfd416b 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h | |||
@@ -28,6 +28,7 @@ struct machine { | |||
28 | pid_t pid; | 28 | pid_t pid; |
29 | u16 id_hdr_size; | 29 | u16 id_hdr_size; |
30 | bool comm_exec; | 30 | bool comm_exec; |
31 | bool kptr_restrict_warned; | ||
31 | char *root_dir; | 32 | char *root_dir; |
32 | struct rb_root threads; | 33 | struct rb_root threads; |
33 | pthread_rwlock_t threads_lock; | 34 | pthread_rwlock_t threads_lock; |
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 62c7f6988e0e..5d1eb1ccd96c 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c | |||
@@ -264,8 +264,7 @@ static SV *perl_process_callchain(struct perf_sample *sample, | |||
264 | goto exit; | 264 | goto exit; |
265 | 265 | ||
266 | if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel, | 266 | if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel, |
267 | sample, NULL, NULL, | 267 | sample, NULL, NULL, scripting_max_stack) != 0) { |
268 | sysctl_perf_event_max_stack) != 0) { | ||
269 | pr_err("Failed to resolve callchain. Skipping\n"); | 268 | pr_err("Failed to resolve callchain. Skipping\n"); |
270 | goto exit; | 269 | goto exit; |
271 | } | 270 | } |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 20e69edd5006..c4e9bd70723c 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -353,6 +353,88 @@ struct sort_entry sort_srcline = { | |||
353 | .se_width_idx = HISTC_SRCLINE, | 353 | .se_width_idx = HISTC_SRCLINE, |
354 | }; | 354 | }; |
355 | 355 | ||
356 | /* --sort srcline_from */ | ||
357 | |||
358 | static int64_t | ||
359 | sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right) | ||
360 | { | ||
361 | if (!left->branch_info->srcline_from) { | ||
362 | struct map *map = left->branch_info->from.map; | ||
363 | if (!map) | ||
364 | left->branch_info->srcline_from = SRCLINE_UNKNOWN; | ||
365 | else | ||
366 | left->branch_info->srcline_from = get_srcline(map->dso, | ||
367 | map__rip_2objdump(map, | ||
368 | left->branch_info->from.al_addr), | ||
369 | left->branch_info->from.sym, true); | ||
370 | } | ||
371 | if (!right->branch_info->srcline_from) { | ||
372 | struct map *map = right->branch_info->from.map; | ||
373 | if (!map) | ||
374 | right->branch_info->srcline_from = SRCLINE_UNKNOWN; | ||
375 | else | ||
376 | right->branch_info->srcline_from = get_srcline(map->dso, | ||
377 | map__rip_2objdump(map, | ||
378 | right->branch_info->from.al_addr), | ||
379 | right->branch_info->from.sym, true); | ||
380 | } | ||
381 | return strcmp(right->branch_info->srcline_from, left->branch_info->srcline_from); | ||
382 | } | ||
383 | |||
384 | static int hist_entry__srcline_from_snprintf(struct hist_entry *he, char *bf, | ||
385 | size_t size, unsigned int width) | ||
386 | { | ||
387 | return repsep_snprintf(bf, size, "%-*.*s", width, width, he->branch_info->srcline_from); | ||
388 | } | ||
389 | |||
390 | struct sort_entry sort_srcline_from = { | ||
391 | .se_header = "From Source:Line", | ||
392 | .se_cmp = sort__srcline_from_cmp, | ||
393 | .se_snprintf = hist_entry__srcline_from_snprintf, | ||
394 | .se_width_idx = HISTC_SRCLINE_FROM, | ||
395 | }; | ||
396 | |||
397 | /* --sort srcline_to */ | ||
398 | |||
399 | static int64_t | ||
400 | sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right) | ||
401 | { | ||
402 | if (!left->branch_info->srcline_to) { | ||
403 | struct map *map = left->branch_info->to.map; | ||
404 | if (!map) | ||
405 | left->branch_info->srcline_to = SRCLINE_UNKNOWN; | ||
406 | else | ||
407 | left->branch_info->srcline_to = get_srcline(map->dso, | ||
408 | map__rip_2objdump(map, | ||
409 | left->branch_info->to.al_addr), | ||
410 | left->branch_info->from.sym, true); | ||
411 | } | ||
412 | if (!right->branch_info->srcline_to) { | ||
413 | struct map *map = right->branch_info->to.map; | ||
414 | if (!map) | ||
415 | right->branch_info->srcline_to = SRCLINE_UNKNOWN; | ||
416 | else | ||
417 | right->branch_info->srcline_to = get_srcline(map->dso, | ||
418 | map__rip_2objdump(map, | ||
419 | right->branch_info->to.al_addr), | ||
420 | right->branch_info->to.sym, true); | ||
421 | } | ||
422 | return strcmp(right->branch_info->srcline_to, left->branch_info->srcline_to); | ||
423 | } | ||
424 | |||
425 | static int hist_entry__srcline_to_snprintf(struct hist_entry *he, char *bf, | ||
426 | size_t size, unsigned int width) | ||
427 | { | ||
428 | return repsep_snprintf(bf, size, "%-*.*s", width, width, he->branch_info->srcline_to); | ||
429 | } | ||
430 | |||
431 | struct sort_entry sort_srcline_to = { | ||
432 | .se_header = "To Source:Line", | ||
433 | .se_cmp = sort__srcline_to_cmp, | ||
434 | .se_snprintf = hist_entry__srcline_to_snprintf, | ||
435 | .se_width_idx = HISTC_SRCLINE_TO, | ||
436 | }; | ||
437 | |||
356 | /* --sort srcfile */ | 438 | /* --sort srcfile */ |
357 | 439 | ||
358 | static char no_srcfile[1]; | 440 | static char no_srcfile[1]; |
@@ -1347,6 +1429,8 @@ static struct sort_dimension bstack_sort_dimensions[] = { | |||
1347 | DIM(SORT_IN_TX, "in_tx", sort_in_tx), | 1429 | DIM(SORT_IN_TX, "in_tx", sort_in_tx), |
1348 | DIM(SORT_ABORT, "abort", sort_abort), | 1430 | DIM(SORT_ABORT, "abort", sort_abort), |
1349 | DIM(SORT_CYCLES, "cycles", sort_cycles), | 1431 | DIM(SORT_CYCLES, "cycles", sort_cycles), |
1432 | DIM(SORT_SRCLINE_FROM, "srcline_from", sort_srcline_from), | ||
1433 | DIM(SORT_SRCLINE_TO, "srcline_to", sort_srcline_to), | ||
1350 | }; | 1434 | }; |
1351 | 1435 | ||
1352 | #undef DIM | 1436 | #undef DIM |
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 42927f448bcb..ebb59cacd092 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h | |||
@@ -215,6 +215,8 @@ enum sort_type { | |||
215 | SORT_ABORT, | 215 | SORT_ABORT, |
216 | SORT_IN_TX, | 216 | SORT_IN_TX, |
217 | SORT_CYCLES, | 217 | SORT_CYCLES, |
218 | SORT_SRCLINE_FROM, | ||
219 | SORT_SRCLINE_TO, | ||
218 | 220 | ||
219 | /* memory mode specific sort keys */ | 221 | /* memory mode specific sort keys */ |
220 | __SORT_MEMORY_MODE, | 222 | __SORT_MEMORY_MODE, |
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index fdb71961143e..aa9efe08762b 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c | |||
@@ -94,7 +94,8 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count, | |||
94 | { | 94 | { |
95 | int ctx = evsel_context(counter); | 95 | int ctx = evsel_context(counter); |
96 | 96 | ||
97 | if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK)) | 97 | if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK) || |
98 | perf_evsel__match(counter, SOFTWARE, SW_CPU_CLOCK)) | ||
98 | update_stats(&runtime_nsecs_stats[cpu], count[0]); | 99 | update_stats(&runtime_nsecs_stats[cpu], count[0]); |
99 | else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) | 100 | else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) |
100 | update_stats(&runtime_cycles_stats[ctx][cpu], count[0]); | 101 | update_stats(&runtime_cycles_stats[ctx][cpu], count[0]); |
@@ -188,7 +189,7 @@ static void print_stalled_cycles_backend(int cpu, | |||
188 | 189 | ||
189 | color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio); | 190 | color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio); |
190 | 191 | ||
191 | out->print_metric(out->ctx, color, "%6.2f%%", "backend cycles idle", ratio); | 192 | out->print_metric(out->ctx, color, "%7.2f%%", "backend cycles idle", ratio); |
192 | } | 193 | } |
193 | 194 | ||
194 | static void print_branch_misses(int cpu, | 195 | static void print_branch_misses(int cpu, |
@@ -444,7 +445,8 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, | |||
444 | ratio = total / avg; | 445 | ratio = total / avg; |
445 | 446 | ||
446 | print_metric(ctxp, NULL, "%8.0f", "cycles / elision", ratio); | 447 | print_metric(ctxp, NULL, "%8.0f", "cycles / elision", ratio); |
447 | } else if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) { | 448 | } else if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK) || |
449 | perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK)) { | ||
448 | if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0) | 450 | if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0) |
449 | print_metric(ctxp, NULL, "%8.3f", "CPUs utilized", | 451 | print_metric(ctxp, NULL, "%8.3f", "CPUs utilized", |
450 | avg / ratio); | 452 | avg / ratio); |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 7fb33304fb4e..54c4ff2b1cee 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -1662,8 +1662,8 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map) | |||
1662 | 1662 | ||
1663 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); | 1663 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); |
1664 | 1664 | ||
1665 | scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s", buildid_dir, | 1665 | scnprintf(path, sizeof(path), "%s/%s/%s", buildid_dir, |
1666 | sbuild_id); | 1666 | DSO__NAME_KCORE, sbuild_id); |
1667 | 1667 | ||
1668 | /* Use /proc/kallsyms if possible */ | 1668 | /* Use /proc/kallsyms if possible */ |
1669 | if (is_host) { | 1669 | if (is_host) { |
@@ -1699,8 +1699,8 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map) | |||
1699 | if (!find_matching_kcore(map, path, sizeof(path))) | 1699 | if (!find_matching_kcore(map, path, sizeof(path))) |
1700 | return strdup(path); | 1700 | return strdup(path); |
1701 | 1701 | ||
1702 | scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s", | 1702 | scnprintf(path, sizeof(path), "%s/%s/%s", |
1703 | buildid_dir, sbuild_id); | 1703 | buildid_dir, DSO__NAME_KALLSYMS, sbuild_id); |
1704 | 1704 | ||
1705 | if (access(path, F_OK)) { | 1705 | if (access(path, F_OK)) { |
1706 | pr_err("No kallsyms or vmlinux with build-id %s was found\n", | 1706 | pr_err("No kallsyms or vmlinux with build-id %s was found\n", |
@@ -1769,7 +1769,7 @@ do_kallsyms: | |||
1769 | 1769 | ||
1770 | if (err > 0 && !dso__is_kcore(dso)) { | 1770 | if (err > 0 && !dso__is_kcore(dso)) { |
1771 | dso->binary_type = DSO_BINARY_TYPE__KALLSYMS; | 1771 | dso->binary_type = DSO_BINARY_TYPE__KALLSYMS; |
1772 | dso__set_long_name(dso, "[kernel.kallsyms]", false); | 1772 | dso__set_long_name(dso, DSO__NAME_KALLSYMS, false); |
1773 | map__fixup_start(map); | 1773 | map__fixup_start(map); |
1774 | map__fixup_end(map); | 1774 | map__fixup_end(map); |
1775 | } | 1775 | } |
@@ -1933,17 +1933,17 @@ int setup_intlist(struct intlist **list, const char *list_str, | |||
1933 | static bool symbol__read_kptr_restrict(void) | 1933 | static bool symbol__read_kptr_restrict(void) |
1934 | { | 1934 | { |
1935 | bool value = false; | 1935 | bool value = false; |
1936 | FILE *fp = fopen("/proc/sys/kernel/kptr_restrict", "r"); | ||
1936 | 1937 | ||
1937 | if (geteuid() != 0) { | 1938 | if (fp != NULL) { |
1938 | FILE *fp = fopen("/proc/sys/kernel/kptr_restrict", "r"); | 1939 | char line[8]; |
1939 | if (fp != NULL) { | ||
1940 | char line[8]; | ||
1941 | 1940 | ||
1942 | if (fgets(line, sizeof(line), fp) != NULL) | 1941 | if (fgets(line, sizeof(line), fp) != NULL) |
1943 | value = atoi(line) != 0; | 1942 | value = (geteuid() != 0) ? |
1943 | (atoi(line) != 0) : | ||
1944 | (atoi(line) == 2); | ||
1944 | 1945 | ||
1945 | fclose(fp); | 1946 | fclose(fp); |
1946 | } | ||
1947 | } | 1947 | } |
1948 | 1948 | ||
1949 | return value; | 1949 | return value; |
@@ -2033,3 +2033,26 @@ void symbol__exit(void) | |||
2033 | symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL; | 2033 | symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL; |
2034 | symbol_conf.initialized = false; | 2034 | symbol_conf.initialized = false; |
2035 | } | 2035 | } |
2036 | |||
2037 | int symbol__config_symfs(const struct option *opt __maybe_unused, | ||
2038 | const char *dir, int unset __maybe_unused) | ||
2039 | { | ||
2040 | char *bf = NULL; | ||
2041 | int ret; | ||
2042 | |||
2043 | symbol_conf.symfs = strdup(dir); | ||
2044 | if (symbol_conf.symfs == NULL) | ||
2045 | return -ENOMEM; | ||
2046 | |||
2047 | /* skip the locally configured cache if a symfs is given, and | ||
2048 | * config buildid dir to symfs/.debug | ||
2049 | */ | ||
2050 | ret = asprintf(&bf, "%s/%s", dir, ".debug"); | ||
2051 | if (ret < 0) | ||
2052 | return -ENOMEM; | ||
2053 | |||
2054 | set_buildid_dir(bf); | ||
2055 | |||
2056 | free(bf); | ||
2057 | return 0; | ||
2058 | } | ||
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 2b5e4ed76fcb..b10d558a8803 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -44,6 +44,9 @@ Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, | |||
44 | #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ | 44 | #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | #define DSO__NAME_KALLSYMS "[kernel.kallsyms]" | ||
48 | #define DSO__NAME_KCORE "[kernel.kcore]" | ||
49 | |||
47 | /** struct symbol - symtab entry | 50 | /** struct symbol - symtab entry |
48 | * | 51 | * |
49 | * @ignore - resolvable but tools ignore it (e.g. idle routines) | 52 | * @ignore - resolvable but tools ignore it (e.g. idle routines) |
@@ -183,6 +186,8 @@ struct branch_info { | |||
183 | struct addr_map_symbol from; | 186 | struct addr_map_symbol from; |
184 | struct addr_map_symbol to; | 187 | struct addr_map_symbol to; |
185 | struct branch_flags flags; | 188 | struct branch_flags flags; |
189 | char *srcline_from; | ||
190 | char *srcline_to; | ||
186 | }; | 191 | }; |
187 | 192 | ||
188 | struct mem_info { | 193 | struct mem_info { |
@@ -287,6 +292,8 @@ bool symbol_type__is_a(char symbol_type, enum map_type map_type); | |||
287 | bool symbol__restricted_filename(const char *filename, | 292 | bool symbol__restricted_filename(const char *filename, |
288 | const char *restricted_filename); | 293 | const char *restricted_filename); |
289 | bool symbol__is_idle(struct symbol *sym); | 294 | bool symbol__is_idle(struct symbol *sym); |
295 | int symbol__config_symfs(const struct option *opt __maybe_unused, | ||
296 | const char *dir, int unset __maybe_unused); | ||
290 | 297 | ||
291 | int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, | 298 | int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, |
292 | struct symsrc *runtime_ss, symbol_filter_t filter, | 299 | struct symsrc *runtime_ss, symbol_filter_t filter, |
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h index f92c37abb0a8..b2940c88734a 100644 --- a/tools/perf/util/top.h +++ b/tools/perf/util/top.h | |||
@@ -27,7 +27,6 @@ struct perf_top { | |||
27 | int max_stack; | 27 | int max_stack; |
28 | bool hide_kernel_symbols, hide_user_symbols, zero; | 28 | bool hide_kernel_symbols, hide_user_symbols, zero; |
29 | bool use_tui, use_stdio; | 29 | bool use_tui, use_stdio; |
30 | bool kptr_restrict_warned; | ||
31 | bool vmlinux_warned; | 30 | bool vmlinux_warned; |
32 | bool dump_symtab; | 31 | bool dump_symtab; |
33 | struct hist_entry *sym_filter_entry; | 32 | struct hist_entry *sym_filter_entry; |
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index eab077ad6ca9..23504ad5d6dd 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c | |||
@@ -33,7 +33,8 @@ struct callchain_param callchain_param = { | |||
33 | unsigned int page_size; | 33 | unsigned int page_size; |
34 | int cacheline_size; | 34 | int cacheline_size; |
35 | 35 | ||
36 | unsigned int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH; | 36 | int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH; |
37 | int sysctl_perf_event_max_contexts_per_stack = PERF_MAX_CONTEXTS_PER_STACK; | ||
37 | 38 | ||
38 | bool test_attr__enabled; | 39 | bool test_attr__enabled; |
39 | 40 | ||
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 7651633a8dc7..1e8c3167b9fb 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -261,7 +261,8 @@ void sighandler_dump_stack(int sig); | |||
261 | 261 | ||
262 | extern unsigned int page_size; | 262 | extern unsigned int page_size; |
263 | extern int cacheline_size; | 263 | extern int cacheline_size; |
264 | extern unsigned int sysctl_perf_event_max_stack; | 264 | extern int sysctl_perf_event_max_stack; |
265 | extern int sysctl_perf_event_max_contexts_per_stack; | ||
265 | 266 | ||
266 | struct parse_tag { | 267 | struct parse_tag { |
267 | char tag; | 268 | char tag; |
diff --git a/tools/testing/radix-tree/tag_check.c b/tools/testing/radix-tree/tag_check.c index b7447ceb75e9..b0ac05741750 100644 --- a/tools/testing/radix-tree/tag_check.c +++ b/tools/testing/radix-tree/tag_check.c | |||
@@ -122,7 +122,7 @@ enum { | |||
122 | NODE_TAGGED = 2, | 122 | NODE_TAGGED = 2, |
123 | }; | 123 | }; |
124 | 124 | ||
125 | #define THRASH_SIZE 1000 * 1000 | 125 | #define THRASH_SIZE (1000 * 1000) |
126 | #define N 127 | 126 | #define N 127 |
127 | #define BATCH 33 | 127 | #define BATCH 33 |
128 | 128 | ||
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc index c2b61c4fda11..0bf5085281f3 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc | |||
@@ -23,15 +23,14 @@ if [ ! -f events/sched/sched_process_fork/trigger ]; then | |||
23 | exit_unsupported | 23 | exit_unsupported |
24 | fi | 24 | fi |
25 | 25 | ||
26 | reset_tracer | 26 | if [ ! -f events/sched/sched_process_fork/hist ]; then |
27 | do_reset | ||
28 | |||
29 | FEATURE=`grep hist events/sched/sched_process_fork/trigger` | ||
30 | if [ -z "$FEATURE" ]; then | ||
31 | echo "hist trigger is not supported" | 27 | echo "hist trigger is not supported" |
32 | exit_unsupported | 28 | exit_unsupported |
33 | fi | 29 | fi |
34 | 30 | ||
31 | reset_tracer | ||
32 | do_reset | ||
33 | |||
35 | echo "Test histogram with execname modifier" | 34 | echo "Test histogram with execname modifier" |
36 | 35 | ||
37 | echo 'hist:keys=common_pid.execname' > events/sched/sched_process_fork/trigger | 36 | echo 'hist:keys=common_pid.execname' > events/sched/sched_process_fork/trigger |
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc index b2902d42a537..a00184cd9c95 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc | |||
@@ -23,15 +23,14 @@ if [ ! -f events/sched/sched_process_fork/trigger ]; then | |||
23 | exit_unsupported | 23 | exit_unsupported |
24 | fi | 24 | fi |
25 | 25 | ||
26 | reset_tracer | 26 | if [ ! -f events/sched/sched_process_fork/hist ]; then |
27 | do_reset | ||
28 | |||
29 | FEATURE=`grep hist events/sched/sched_process_fork/trigger` | ||
30 | if [ -z "$FEATURE" ]; then | ||
31 | echo "hist trigger is not supported" | 27 | echo "hist trigger is not supported" |
32 | exit_unsupported | 28 | exit_unsupported |
33 | fi | 29 | fi |
34 | 30 | ||
31 | reset_tracer | ||
32 | do_reset | ||
33 | |||
35 | echo "Test histogram basic tigger" | 34 | echo "Test histogram basic tigger" |
36 | 35 | ||
37 | echo 'hist:keys=parent_pid:vals=child_pid' > events/sched/sched_process_fork/trigger | 36 | echo 'hist:keys=parent_pid:vals=child_pid' > events/sched/sched_process_fork/trigger |
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc index 03c4a46561fc..3478b00ead57 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc | |||
@@ -23,15 +23,14 @@ if [ ! -f events/sched/sched_process_fork/trigger ]; then | |||
23 | exit_unsupported | 23 | exit_unsupported |
24 | fi | 24 | fi |
25 | 25 | ||
26 | reset_tracer | 26 | if [ ! -f events/sched/sched_process_fork/hist ]; then |
27 | do_reset | ||
28 | |||
29 | FEATURE=`grep hist events/sched/sched_process_fork/trigger` | ||
30 | if [ -z "$FEATURE" ]; then | ||
31 | echo "hist trigger is not supported" | 27 | echo "hist trigger is not supported" |
32 | exit_unsupported | 28 | exit_unsupported |
33 | fi | 29 | fi |
34 | 30 | ||
31 | reset_tracer | ||
32 | do_reset | ||
33 | |||
35 | reset_trigger | 34 | reset_trigger |
36 | 35 | ||
37 | echo "Test histogram multiple tiggers" | 36 | echo "Test histogram multiple tiggers" |
diff --git a/tools/testing/selftests/net/reuseport_bpf.c b/tools/testing/selftests/net/reuseport_bpf.c index 96ba386b1b7b..4a8217448f20 100644 --- a/tools/testing/selftests/net/reuseport_bpf.c +++ b/tools/testing/selftests/net/reuseport_bpf.c | |||
@@ -111,9 +111,9 @@ static void attach_ebpf(int fd, uint16_t mod) | |||
111 | memset(&attr, 0, sizeof(attr)); | 111 | memset(&attr, 0, sizeof(attr)); |
112 | attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER; | 112 | attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER; |
113 | attr.insn_cnt = ARRAY_SIZE(prog); | 113 | attr.insn_cnt = ARRAY_SIZE(prog); |
114 | attr.insns = (uint64_t)prog; | 114 | attr.insns = (unsigned long) &prog; |
115 | attr.license = (uint64_t)bpf_license; | 115 | attr.license = (unsigned long) &bpf_license; |
116 | attr.log_buf = (uint64_t)bpf_log_buf; | 116 | attr.log_buf = (unsigned long) &bpf_log_buf; |
117 | attr.log_size = sizeof(bpf_log_buf); | 117 | attr.log_size = sizeof(bpf_log_buf); |
118 | attr.log_level = 1; | 118 | attr.log_level = 1; |
119 | attr.kern_version = 0; | 119 | attr.kern_version = 0; |
@@ -351,8 +351,8 @@ static void test_filter_no_reuseport(const struct test_params p) | |||
351 | memset(&eprog, 0, sizeof(eprog)); | 351 | memset(&eprog, 0, sizeof(eprog)); |
352 | eprog.prog_type = BPF_PROG_TYPE_SOCKET_FILTER; | 352 | eprog.prog_type = BPF_PROG_TYPE_SOCKET_FILTER; |
353 | eprog.insn_cnt = ARRAY_SIZE(ecode); | 353 | eprog.insn_cnt = ARRAY_SIZE(ecode); |
354 | eprog.insns = (uint64_t)ecode; | 354 | eprog.insns = (unsigned long) &ecode; |
355 | eprog.license = (uint64_t)bpf_license; | 355 | eprog.license = (unsigned long) &bpf_license; |
356 | eprog.kern_version = 0; | 356 | eprog.kern_version = 0; |
357 | 357 | ||
358 | memset(&cprog, 0, sizeof(cprog)); | 358 | memset(&cprog, 0, sizeof(cprog)); |
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c index 7947e568e057..2e58549b2f02 100644 --- a/tools/testing/selftests/seccomp/seccomp_bpf.c +++ b/tools/testing/selftests/seccomp/seccomp_bpf.c | |||
@@ -1234,6 +1234,10 @@ TEST_F(TRACE_poke, getpid_runs_normally) | |||
1234 | # define ARCH_REGS struct user_pt_regs | 1234 | # define ARCH_REGS struct user_pt_regs |
1235 | # define SYSCALL_NUM regs[8] | 1235 | # define SYSCALL_NUM regs[8] |
1236 | # define SYSCALL_RET regs[0] | 1236 | # define SYSCALL_RET regs[0] |
1237 | #elif defined(__hppa__) | ||
1238 | # define ARCH_REGS struct user_regs_struct | ||
1239 | # define SYSCALL_NUM gr[20] | ||
1240 | # define SYSCALL_RET gr[28] | ||
1237 | #elif defined(__powerpc__) | 1241 | #elif defined(__powerpc__) |
1238 | # define ARCH_REGS struct pt_regs | 1242 | # define ARCH_REGS struct pt_regs |
1239 | # define SYSCALL_NUM gpr[0] | 1243 | # define SYSCALL_NUM gpr[0] |
@@ -1303,7 +1307,7 @@ void change_syscall(struct __test_metadata *_metadata, | |||
1303 | EXPECT_EQ(0, ret); | 1307 | EXPECT_EQ(0, ret); |
1304 | 1308 | ||
1305 | #if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \ | 1309 | #if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \ |
1306 | defined(__s390__) | 1310 | defined(__s390__) || defined(__hppa__) |
1307 | { | 1311 | { |
1308 | regs.SYSCALL_NUM = syscall; | 1312 | regs.SYSCALL_NUM = syscall; |
1309 | } | 1313 | } |
@@ -1505,6 +1509,8 @@ TEST_F(TRACE_syscall, syscall_dropped) | |||
1505 | # define __NR_seccomp 383 | 1509 | # define __NR_seccomp 383 |
1506 | # elif defined(__aarch64__) | 1510 | # elif defined(__aarch64__) |
1507 | # define __NR_seccomp 277 | 1511 | # define __NR_seccomp 277 |
1512 | # elif defined(__hppa__) | ||
1513 | # define __NR_seccomp 338 | ||
1508 | # elif defined(__powerpc__) | 1514 | # elif defined(__powerpc__) |
1509 | # define __NR_seccomp 358 | 1515 | # define __NR_seccomp 358 |
1510 | # elif defined(__s390__) | 1516 | # elif defined(__s390__) |
diff --git a/tools/testing/selftests/vm/compaction_test.c b/tools/testing/selftests/vm/compaction_test.c index 932ff577ffc0..00c4f65d12da 100644 --- a/tools/testing/selftests/vm/compaction_test.c +++ b/tools/testing/selftests/vm/compaction_test.c | |||
@@ -136,7 +136,7 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size) | |||
136 | printf("No of huge pages allocated = %d\n", | 136 | printf("No of huge pages allocated = %d\n", |
137 | (atoi(nr_hugepages))); | 137 | (atoi(nr_hugepages))); |
138 | 138 | ||
139 | if (write(fd, initial_nr_hugepages, sizeof(initial_nr_hugepages)) | 139 | if (write(fd, initial_nr_hugepages, strlen(initial_nr_hugepages)) |
140 | != strlen(initial_nr_hugepages)) { | 140 | != strlen(initial_nr_hugepages)) { |
141 | perror("Failed to write to /proc/sys/vm/nr_hugepages\n"); | 141 | perror("Failed to write to /proc/sys/vm/nr_hugepages\n"); |
142 | goto close_fd; | 142 | goto close_fd; |
diff --git a/tools/testing/selftests/vm/thuge-gen.c b/tools/testing/selftests/vm/thuge-gen.c index c87957295f74..0bc737a75150 100644 --- a/tools/testing/selftests/vm/thuge-gen.c +++ b/tools/testing/selftests/vm/thuge-gen.c | |||
@@ -30,7 +30,9 @@ | |||
30 | #define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT) | 30 | #define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT) |
31 | #define MAP_HUGE_SHIFT 26 | 31 | #define MAP_HUGE_SHIFT 26 |
32 | #define MAP_HUGE_MASK 0x3f | 32 | #define MAP_HUGE_MASK 0x3f |
33 | #if !defined(MAP_HUGETLB) | ||
33 | #define MAP_HUGETLB 0x40000 | 34 | #define MAP_HUGETLB 0x40000 |
35 | #endif | ||
34 | 36 | ||
35 | #define SHM_HUGETLB 04000 /* segment will use huge TLB pages */ | 37 | #define SHM_HUGETLB 04000 /* segment will use huge TLB pages */ |
36 | #define SHM_HUGE_SHIFT 26 | 38 | #define SHM_HUGE_SHIFT 26 |
diff --git a/tools/virtio/ringtest/Makefile b/tools/virtio/ringtest/Makefile index 6ba745529833..6173adae9f08 100644 --- a/tools/virtio/ringtest/Makefile +++ b/tools/virtio/ringtest/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | all: | 1 | all: |
2 | 2 | ||
3 | all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder | 3 | all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder noring |
4 | 4 | ||
5 | CFLAGS += -Wall | 5 | CFLAGS += -Wall |
6 | CFLAGS += -pthread -O2 -ggdb | 6 | CFLAGS += -pthread -O2 -ggdb |
@@ -15,11 +15,13 @@ ring: ring.o main.o | |||
15 | virtio_ring_0_9: virtio_ring_0_9.o main.o | 15 | virtio_ring_0_9: virtio_ring_0_9.o main.o |
16 | virtio_ring_poll: virtio_ring_poll.o main.o | 16 | virtio_ring_poll: virtio_ring_poll.o main.o |
17 | virtio_ring_inorder: virtio_ring_inorder.o main.o | 17 | virtio_ring_inorder: virtio_ring_inorder.o main.o |
18 | noring: noring.o main.o | ||
18 | clean: | 19 | clean: |
19 | -rm main.o | 20 | -rm main.o |
20 | -rm ring.o ring | 21 | -rm ring.o ring |
21 | -rm virtio_ring_0_9.o virtio_ring_0_9 | 22 | -rm virtio_ring_0_9.o virtio_ring_0_9 |
22 | -rm virtio_ring_poll.o virtio_ring_poll | 23 | -rm virtio_ring_poll.o virtio_ring_poll |
23 | -rm virtio_ring_inorder.o virtio_ring_inorder | 24 | -rm virtio_ring_inorder.o virtio_ring_inorder |
25 | -rm noring.o noring | ||
24 | 26 | ||
25 | .PHONY: all clean | 27 | .PHONY: all clean |
diff --git a/tools/virtio/ringtest/README b/tools/virtio/ringtest/README index 34e94c46104f..d83707a336c9 100644 --- a/tools/virtio/ringtest/README +++ b/tools/virtio/ringtest/README | |||
@@ -1,2 +1,6 @@ | |||
1 | Partial implementation of various ring layouts, useful to tune virtio design. | 1 | Partial implementation of various ring layouts, useful to tune virtio design. |
2 | Uses shared memory heavily. | 2 | Uses shared memory heavily. |
3 | |||
4 | Typical use: | ||
5 | |||
6 | # sh run-on-all.sh perf stat -r 10 --log-fd 1 -- ./ring | ||
diff --git a/tools/virtio/ringtest/noring.c b/tools/virtio/ringtest/noring.c new file mode 100644 index 000000000000..eda2f4824130 --- /dev/null +++ b/tools/virtio/ringtest/noring.c | |||
@@ -0,0 +1,69 @@ | |||
1 | #define _GNU_SOURCE | ||
2 | #include "main.h" | ||
3 | #include <assert.h> | ||
4 | |||
5 | /* stub implementation: useful for measuring overhead */ | ||
6 | void alloc_ring(void) | ||
7 | { | ||
8 | } | ||
9 | |||
10 | /* guest side */ | ||
11 | int add_inbuf(unsigned len, void *buf, void *datap) | ||
12 | { | ||
13 | return 0; | ||
14 | } | ||
15 | |||
16 | /* | ||
17 | * skb_array API provides no way for producer to find out whether a given | ||
18 | * buffer was consumed. Our tests merely require that a successful get_buf | ||
19 | * implies that add_inbuf succeed in the past, and that add_inbuf will succeed, | ||
20 | * fake it accordingly. | ||
21 | */ | ||
22 | void *get_buf(unsigned *lenp, void **bufp) | ||
23 | { | ||
24 | return "Buffer"; | ||
25 | } | ||
26 | |||
27 | void poll_used(void) | ||
28 | { | ||
29 | } | ||
30 | |||
31 | void disable_call() | ||
32 | { | ||
33 | assert(0); | ||
34 | } | ||
35 | |||
36 | bool enable_call() | ||
37 | { | ||
38 | assert(0); | ||
39 | } | ||
40 | |||
41 | void kick_available(void) | ||
42 | { | ||
43 | assert(0); | ||
44 | } | ||
45 | |||
46 | /* host side */ | ||
47 | void disable_kick() | ||
48 | { | ||
49 | assert(0); | ||
50 | } | ||
51 | |||
52 | bool enable_kick() | ||
53 | { | ||
54 | assert(0); | ||
55 | } | ||
56 | |||
57 | void poll_avail(void) | ||
58 | { | ||
59 | } | ||
60 | |||
61 | bool use_buf(unsigned *lenp, void **bufp) | ||
62 | { | ||
63 | return true; | ||
64 | } | ||
65 | |||
66 | void call_used(void) | ||
67 | { | ||
68 | assert(0); | ||
69 | } | ||
diff --git a/tools/virtio/ringtest/run-on-all.sh b/tools/virtio/ringtest/run-on-all.sh index 52b0f71ffa8d..2e69ca812b4c 100755 --- a/tools/virtio/ringtest/run-on-all.sh +++ b/tools/virtio/ringtest/run-on-all.sh | |||
@@ -3,10 +3,10 @@ | |||
3 | #use last CPU for host. Why not the first? | 3 | #use last CPU for host. Why not the first? |
4 | #many devices tend to use cpu0 by default so | 4 | #many devices tend to use cpu0 by default so |
5 | #it tends to be busier | 5 | #it tends to be busier |
6 | HOST_AFFINITY=$(cd /dev/cpu; ls|grep -v '[a-z]'|sort -n|tail -1) | 6 | HOST_AFFINITY=$(lscpu -p=cpu | tail -1) |
7 | 7 | ||
8 | #run command on all cpus | 8 | #run command on all cpus |
9 | for cpu in $(cd /dev/cpu; ls|grep -v '[a-z]'|sort -n); | 9 | for cpu in $(seq 0 $HOST_AFFINITY) |
10 | do | 10 | do |
11 | #Don't run guest and host on same CPU | 11 | #Don't run guest and host on same CPU |
12 | #It actually works ok if using signalling | 12 | #It actually works ok if using signalling |
diff --git a/tools/vm/slabinfo.c b/tools/vm/slabinfo.c index 1889163f2f05..b9d34b37c017 100644 --- a/tools/vm/slabinfo.c +++ b/tools/vm/slabinfo.c | |||
@@ -492,7 +492,7 @@ static void slab_stats(struct slabinfo *s) | |||
492 | s->deactivate_to_head + s->deactivate_to_tail + s->deactivate_bypass; | 492 | s->deactivate_to_head + s->deactivate_to_tail + s->deactivate_bypass; |
493 | 493 | ||
494 | if (total) { | 494 | if (total) { |
495 | printf("\nSlab Deactivation Ocurrences %%\n"); | 495 | printf("\nSlab Deactivation Occurrences %%\n"); |
496 | printf("-------------------------------------------------\n"); | 496 | printf("-------------------------------------------------\n"); |
497 | printf("Slab full %7lu %3lu%%\n", | 497 | printf("Slab full %7lu %3lu%%\n", |
498 | s->deactivate_full, (s->deactivate_full * 100) / total); | 498 | s->deactivate_full, (s->deactivate_full * 100) / total); |
@@ -510,10 +510,11 @@ static void slab_stats(struct slabinfo *s) | |||
510 | s->alloc_node_mismatch, (s->alloc_node_mismatch * 100) / total); | 510 | s->alloc_node_mismatch, (s->alloc_node_mismatch * 100) / total); |
511 | } | 511 | } |
512 | 512 | ||
513 | if (s->cmpxchg_double_fail || s->cmpxchg_double_cpu_fail) | 513 | if (s->cmpxchg_double_fail || s->cmpxchg_double_cpu_fail) { |
514 | printf("\nCmpxchg_double Looping\n------------------------\n"); | 514 | printf("\nCmpxchg_double Looping\n------------------------\n"); |
515 | printf("Locked Cmpxchg Double redos %lu\nUnlocked Cmpxchg Double redos %lu\n", | 515 | printf("Locked Cmpxchg Double redos %lu\nUnlocked Cmpxchg Double redos %lu\n", |
516 | s->cmpxchg_double_fail, s->cmpxchg_double_cpu_fail); | 516 | s->cmpxchg_double_fail, s->cmpxchg_double_cpu_fail); |
517 | } | ||
517 | } | 518 | } |
518 | 519 | ||
519 | static void report(struct slabinfo *s) | 520 | static void report(struct slabinfo *s) |