aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2016-06-03 09:05:51 -0400
committerThomas Gleixner <tglx@linutronix.de>2016-06-03 09:05:51 -0400
commit2eec3707a33fbf1c2e0a88ffc9fc0e465c2a59fd (patch)
tree9e47763ecd38f0ddd29f07e1ce199680304449fa /tools
parent59fa5860204ffc95128d60cba9f54f9740a42c7d (diff)
parent0de6b9979e2e10c79e5702d2d902cd7284d17689 (diff)
Merge tag 'irqchip-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/urgent
Merge irqchip updates from Marc Zyngier: - A number of embarassing buglets (GICv3, PIC32) - A more substential errata workaround for Cavium's GICv3 ITS (kept for post-rc1 due to its dependency on NUMA)
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile6
-rw-r--r--tools/build/Makefile.build8
-rw-r--r--tools/gpio/Makefile2
-rw-r--r--tools/gpio/lsgpio.c2
-rw-r--r--tools/hv/lsvmbus1
-rw-r--r--tools/iio/generic_buffer.c116
-rw-r--r--tools/iio/iio_event_monitor.c18
-rw-r--r--tools/iio/iio_utils.h7
-rw-r--r--tools/kvm/kvm_stat/Makefile41
-rwxr-xr-xtools/kvm/kvm_stat/kvm_stat1127
-rw-r--r--tools/kvm/kvm_stat/kvm_stat.txt63
-rw-r--r--tools/objtool/Makefile4
-rw-r--r--tools/objtool/elf.h5
-rw-r--r--tools/perf/Documentation/perf-report.txt5
-rw-r--r--tools/perf/Documentation/perf-script.txt2
-rw-r--r--tools/perf/Documentation/perf-trace.txt3
-rw-r--r--tools/perf/arch/powerpc/include/perf_regs.h69
-rw-r--r--tools/perf/arch/powerpc/util/Build2
-rw-r--r--tools/perf/arch/powerpc/util/perf_regs.c49
-rw-r--r--tools/perf/arch/powerpc/util/unwind-libunwind.c96
-rw-r--r--tools/perf/builtin-annotate.c5
-rw-r--r--tools/perf/builtin-buildid-cache.c8
-rw-r--r--tools/perf/builtin-diff.c5
-rw-r--r--tools/perf/builtin-record.c81
-rw-r--r--tools/perf/builtin-report.c7
-rw-r--r--tools/perf/builtin-script.c7
-rw-r--r--tools/perf/builtin-stat.c22
-rw-r--r--tools/perf/builtin-timechart.c5
-rw-r--r--tools/perf/builtin-top.c6
-rw-r--r--tools/perf/builtin-trace.c274
-rw-r--r--tools/perf/config/Makefile6
-rw-r--r--tools/perf/perf.c3
-rw-r--r--tools/perf/tests/openat-syscall-all-cpus.c2
-rw-r--r--tools/perf/util/annotate.c32
-rw-r--r--tools/perf/util/build-id.c2
-rw-r--r--tools/perf/util/db-export.c3
-rw-r--r--tools/perf/util/dso.c7
-rw-r--r--tools/perf/util/evlist.c34
-rw-r--r--tools/perf/util/evlist.h4
-rw-r--r--tools/perf/util/evsel.c15
-rw-r--r--tools/perf/util/evsel.h1
-rw-r--r--tools/perf/util/hist.c9
-rw-r--r--tools/perf/util/hist.h2
-rw-r--r--tools/perf/util/machine.c37
-rw-r--r--tools/perf/util/machine.h1
-rw-r--r--tools/perf/util/parse-events.c2
-rw-r--r--tools/perf/util/perf_regs.c8
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c3
-rw-r--r--tools/perf/util/session.c2
-rw-r--r--tools/perf/util/sort.c84
-rw-r--r--tools/perf/util/sort.h2
-rw-r--r--tools/perf/util/stat-shadow.c8
-rw-r--r--tools/perf/util/symbol.c33
-rw-r--r--tools/perf/util/symbol.h7
-rw-r--r--tools/perf/util/top.h1
-rw-r--r--tools/perf/util/util.c3
-rw-r--r--tools/perf/util/util.h3
-rw-r--r--tools/testing/nvdimm/Kbuild11
-rw-r--r--tools/testing/nvdimm/config_check.c2
-rw-r--r--tools/testing/nvdimm/test/iomap.c27
-rw-r--r--tools/testing/nvdimm/test/nfit.c90
-rw-r--r--tools/testing/radix-tree/Makefile4
-rw-r--r--tools/testing/radix-tree/generated/autoconf.h3
-rw-r--r--tools/testing/radix-tree/linux/init.h1
-rw-r--r--tools/testing/radix-tree/linux/kernel.h15
-rw-r--r--tools/testing/radix-tree/linux/slab.h1
-rw-r--r--tools/testing/radix-tree/linux/types.h7
-rw-r--r--tools/testing/radix-tree/main.c84
-rw-r--r--tools/testing/radix-tree/multiorder.c337
-rw-r--r--tools/testing/radix-tree/regression2.c7
-rw-r--r--tools/testing/radix-tree/tag_check.c10
-rw-r--r--tools/testing/radix-tree/test.c49
-rw-r--r--tools/testing/radix-tree/test.h11
-rwxr-xr-xtools/testing/selftests/ftrace/ftracetest9
-rw-r--r--tools/testing/selftests/ftrace/test.d/event/event-pid.tc72
-rw-r--r--tools/testing/selftests/ftrace/test.d/functions9
-rw-r--r--tools/testing/selftests/ftrace/test.d/instances/instance-event.tc138
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc64
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc59
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc75
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc83
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc73
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc56
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc53
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc58
-rwxr-xr-xtools/testing/selftests/intel_pstate/run.sh2
-rw-r--r--tools/testing/selftests/powerpc/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/context_switch/.gitignore1
-rw-r--r--tools/testing/selftests/powerpc/context_switch/Makefile10
-rw-r--r--tools/testing/selftests/powerpc/context_switch/cp_abort.c110
-rw-r--r--tools/testing/selftests/powerpc/mm/subpage_prot.c18
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/ebb.c1
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c1
-rw-r--r--tools/testing/selftests/powerpc/reg.h (renamed from tools/testing/selftests/powerpc/pmu/ebb/reg.h)18
-rw-r--r--tools/testing/selftests/powerpc/tm/.gitignore3
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile3
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-fork.c42
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-resched-dscr.c16
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-stack.c4
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-tar.c90
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-tmspr.c143
-rw-r--r--tools/testing/selftests/powerpc/utils.h8
-rw-r--r--tools/testing/selftests/seccomp/seccomp_bpf.c38
-rw-r--r--tools/testing/selftests/vm/thuge-gen.c2
-rw-r--r--tools/usb/usbip/libsrc/Makefile.am4
-rw-r--r--tools/usb/usbip/libsrc/usbip_common.h3
-rw-r--r--tools/usb/usbip/libsrc/usbip_device_driver.c163
-rw-r--r--tools/usb/usbip/libsrc/usbip_device_driver.h34
-rw-r--r--tools/usb/usbip/libsrc/usbip_host_common.c273
-rw-r--r--tools/usb/usbip/libsrc/usbip_host_common.h104
-rw-r--r--tools/usb/usbip/libsrc/usbip_host_driver.c269
-rw-r--r--tools/usb/usbip/libsrc/usbip_host_driver.h27
-rw-r--r--tools/usb/usbip/src/usbip_attach.c10
-rw-r--r--tools/usb/usbip/src/usbip_list.c96
-rw-r--r--tools/usb/usbip/src/usbip_port.c13
-rw-r--r--tools/usb/usbip/src/usbipd.c42
-rw-r--r--tools/virtio/ringtest/Makefile5
-rw-r--r--tools/virtio/ringtest/main.c2
-rw-r--r--tools/virtio/ringtest/virtio_ring_0_9.c49
-rw-r--r--tools/virtio/ringtest/virtio_ring_inorder.c2
120 files changed, 4718 insertions, 657 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:
110freefall_install: 111freefall_install:
111 $(call descend,laptop/$(@:_install=),install) 112 $(call descend,laptop/$(@:_install=),install)
112 113
114kvm_stat_install:
115 $(call descend,kvm/$(@:_install=),install)
116
113install: acpi_install cgroup_install cpupower_install hv_install firewire_install lguest_install \ 117install: 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
118acpi_clean: 122acpi_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 $@)
58quiet_cmd_cc_o_c = CC $@ 58quiet_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
61quiet_cmd_cc_i_c = CPP $@ 61quiet_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
64quiet_cmd_cc_s_c = AS $@ 64quiet_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/gpio/Makefile b/tools/gpio/Makefile
index 4d198d5c4203..c155d6bc47a7 100644
--- a/tools/gpio/Makefile
+++ b/tools/gpio/Makefile
@@ -1,5 +1,5 @@
1CC = $(CROSS_COMPILE)gcc 1CC = $(CROSS_COMPILE)gcc
2CFLAGS += -Wall -g -D_GNU_SOURCE 2CFLAGS += -O2 -Wall -g -D_GNU_SOURCE
3 3
4all: lsgpio 4all: lsgpio
5 5
diff --git a/tools/gpio/lsgpio.c b/tools/gpio/lsgpio.c
index 1124da375942..eb3f56efd215 100644
--- a/tools/gpio/lsgpio.c
+++ b/tools/gpio/lsgpio.c
@@ -147,7 +147,7 @@ void print_usage(void)
147 147
148int main(int argc, char **argv) 148int main(int argc, char **argv)
149{ 149{
150 const char *device_name; 150 const char *device_name = NULL;
151 int ret; 151 int ret;
152 int c; 152 int c;
153 153
diff --git a/tools/hv/lsvmbus b/tools/hv/lsvmbus
index 162a3784d80e..e8fecd61871f 100644
--- a/tools/hv/lsvmbus
+++ b/tools/hv/lsvmbus
@@ -35,6 +35,7 @@ vmbus_dev_dict = {
35 '{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}' : 'Synthetic SCSI Controller', 35 '{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}' : 'Synthetic SCSI Controller',
36 '{2f9bcc4a-0069-4af3-b76b-6fd0be528cda}' : 'Synthetic fiber channel adapter', 36 '{2f9bcc4a-0069-4af3-b76b-6fd0be528cda}' : 'Synthetic fiber channel adapter',
37 '{8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}' : 'Synthetic RDMA adapter', 37 '{8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}' : 'Synthetic RDMA adapter',
38 '{44c4f61d-4444-4400-9d52-802e27ede19f}' : 'PCI Express pass-through',
38 '{276aacf4-ac15-426c-98dd-7521ad3f01fe}' : '[Reserved system device]', 39 '{276aacf4-ac15-426c-98dd-7521ad3f01fe}' : '[Reserved system device]',
39 '{f8e65716-3cb3-4a06-9a60-1889c5cccab5}' : '[Reserved system device]', 40 '{f8e65716-3cb3-4a06-9a60-1889c5cccab5}' : '[Reserved system device]',
40 '{3375baf4-9e15-4b30-b765-67acb10d607b}' : '[Reserved system device]', 41 '{3375baf4-9e15-4b30-b765-67acb10d607b}' : '[Reserved system device]',
diff --git a/tools/iio/generic_buffer.c b/tools/iio/generic_buffer.c
index 01c4f67801e0..2429c78de940 100644
--- a/tools/iio/generic_buffer.c
+++ b/tools/iio/generic_buffer.c
@@ -35,6 +35,15 @@
35#include "iio_utils.h" 35#include "iio_utils.h"
36 36
37/** 37/**
38 * enum autochan - state for the automatic channel enabling mechanism
39 */
40enum autochan {
41 AUTOCHANNELS_DISABLED,
42 AUTOCHANNELS_ENABLED,
43 AUTOCHANNELS_ACTIVE,
44};
45
46/**
38 * size_from_channelarray() - calculate the storage size of a scan 47 * size_from_channelarray() - calculate the storage size of a scan
39 * @channels: the channel info array 48 * @channels: the channel info array
40 * @num_channels: number of channels 49 * @num_channels: number of channels
@@ -191,10 +200,51 @@ void process_scan(char *data,
191 printf("\n"); 200 printf("\n");
192} 201}
193 202
203static int enable_disable_all_channels(char *dev_dir_name, int enable)
204{
205 const struct dirent *ent;
206 char scanelemdir[256];
207 DIR *dp;
208 int ret;
209
210 snprintf(scanelemdir, sizeof(scanelemdir),
211 FORMAT_SCAN_ELEMENTS_DIR, dev_dir_name);
212 scanelemdir[sizeof(scanelemdir)-1] = '\0';
213
214 dp = opendir(scanelemdir);
215 if (!dp) {
216 fprintf(stderr, "Enabling/disabling channels: can't open %s\n",
217 scanelemdir);
218 return -EIO;
219 }
220
221 ret = -ENOENT;
222 while (ent = readdir(dp), ent) {
223 if (iioutils_check_suffix(ent->d_name, "_en")) {
224 printf("%sabling: %s\n",
225 enable ? "En" : "Dis",
226 ent->d_name);
227 ret = write_sysfs_int(ent->d_name, scanelemdir,
228 enable);
229 if (ret < 0)
230 fprintf(stderr, "Failed to enable/disable %s\n",
231 ent->d_name);
232 }
233 }
234
235 if (closedir(dp) == -1) {
236 perror("Enabling/disabling channels: "
237 "Failed to close directory");
238 return -errno;
239 }
240 return 0;
241}
242
194void print_usage(void) 243void print_usage(void)
195{ 244{
196 fprintf(stderr, "Usage: generic_buffer [options]...\n" 245 fprintf(stderr, "Usage: generic_buffer [options]...\n"
197 "Capture, convert and output data from IIO device buffer\n" 246 "Capture, convert and output data from IIO device buffer\n"
247 " -a Auto-activate all available channels\n"
198 " -c <n> Do n conversions\n" 248 " -c <n> Do n conversions\n"
199 " -e Disable wait for event (new data)\n" 249 " -e Disable wait for event (new data)\n"
200 " -g Use trigger-less mode\n" 250 " -g Use trigger-less mode\n"
@@ -225,12 +275,16 @@ int main(int argc, char **argv)
225 int scan_size; 275 int scan_size;
226 int noevents = 0; 276 int noevents = 0;
227 int notrigger = 0; 277 int notrigger = 0;
278 enum autochan autochannels = AUTOCHANNELS_DISABLED;
228 char *dummy; 279 char *dummy;
229 280
230 struct iio_channel_info *channels; 281 struct iio_channel_info *channels;
231 282
232 while ((c = getopt(argc, argv, "c:egl:n:t:w:")) != -1) { 283 while ((c = getopt(argc, argv, "ac:egl:n:t:w:")) != -1) {
233 switch (c) { 284 switch (c) {
285 case 'a':
286 autochannels = AUTOCHANNELS_ENABLED;
287 break;
234 case 'c': 288 case 'c':
235 errno = 0; 289 errno = 0;
236 num_loops = strtoul(optarg, &dummy, 10); 290 num_loops = strtoul(optarg, &dummy, 10);
@@ -304,7 +358,19 @@ int main(int argc, char **argv)
304 } 358 }
305 } 359 }
306 360
307 /* Verify the trigger exists */ 361 /* Look for this "-devN" trigger */
362 trig_num = find_type_by_name(trigger_name, "trigger");
363 if (trig_num < 0) {
364 /* OK try the simpler "-trigger" suffix instead */
365 free(trigger_name);
366 ret = asprintf(&trigger_name,
367 "%s-trigger", device_name);
368 if (ret < 0) {
369 ret = -ENOMEM;
370 goto error_free_dev_dir_name;
371 }
372 }
373
308 trig_num = find_type_by_name(trigger_name, "trigger"); 374 trig_num = find_type_by_name(trigger_name, "trigger");
309 if (trig_num < 0) { 375 if (trig_num < 0) {
310 fprintf(stderr, "Failed to find the trigger %s\n", 376 fprintf(stderr, "Failed to find the trigger %s\n",
@@ -328,12 +394,47 @@ int main(int argc, char **argv)
328 "diag %s\n", dev_dir_name); 394 "diag %s\n", dev_dir_name);
329 goto error_free_triggername; 395 goto error_free_triggername;
330 } 396 }
331 if (!num_channels) { 397 if (num_channels && autochannels == AUTOCHANNELS_ENABLED) {
398 fprintf(stderr, "Auto-channels selected but some channels "
399 "are already activated in sysfs\n");
400 fprintf(stderr, "Proceeding without activating any channels\n");
401 }
402
403 if (!num_channels && autochannels == AUTOCHANNELS_ENABLED) {
404 fprintf(stderr,
405 "No channels are enabled, enabling all channels\n");
406
407 ret = enable_disable_all_channels(dev_dir_name, 1);
408 if (ret) {
409 fprintf(stderr, "Failed to enable all channels\n");
410 goto error_free_triggername;
411 }
412
413 /* This flags that we need to disable the channels again */
414 autochannels = AUTOCHANNELS_ACTIVE;
415
416 ret = build_channel_array(dev_dir_name, &channels,
417 &num_channels);
418 if (ret) {
419 fprintf(stderr, "Problem reading scan element "
420 "information\n"
421 "diag %s\n", dev_dir_name);
422 goto error_disable_channels;
423 }
424 if (!num_channels) {
425 fprintf(stderr, "Still no channels after "
426 "auto-enabling, giving up\n");
427 goto error_disable_channels;
428 }
429 }
430
431 if (!num_channels && autochannels == AUTOCHANNELS_DISABLED) {
332 fprintf(stderr, 432 fprintf(stderr,
333 "No channels are enabled, we have nothing to scan.\n"); 433 "No channels are enabled, we have nothing to scan.\n");
334 fprintf(stderr, "Enable channels manually in " 434 fprintf(stderr, "Enable channels manually in "
335 FORMAT_SCAN_ELEMENTS_DIR 435 FORMAT_SCAN_ELEMENTS_DIR
336 "/*_en and try again.\n", dev_dir_name); 436 "/*_en or pass -a to autoenable channels and "
437 "try again.\n", dev_dir_name);
337 ret = -ENOENT; 438 ret = -ENOENT;
338 goto error_free_triggername; 439 goto error_free_triggername;
339 } 440 }
@@ -467,7 +568,12 @@ error_free_channels:
467error_free_triggername: 568error_free_triggername:
468 if (datardytrigger) 569 if (datardytrigger)
469 free(trigger_name); 570 free(trigger_name);
470 571error_disable_channels:
572 if (autochannels == AUTOCHANNELS_ACTIVE) {
573 ret = enable_disable_all_channels(dev_dir_name, 0);
574 if (ret)
575 fprintf(stderr, "Failed to disable all channels\n");
576 }
471error_free_dev_dir_name: 577error_free_dev_dir_name:
472 free(dev_dir_name); 578 free(dev_dir_name);
473 579
diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
index d51eb04202e9..d9b7e0f306c6 100644
--- a/tools/iio/iio_event_monitor.c
+++ b/tools/iio/iio_event_monitor.c
@@ -53,6 +53,10 @@ static const char * const iio_chan_type_name_spec[] = {
53 [IIO_ENERGY] = "energy", 53 [IIO_ENERGY] = "energy",
54 [IIO_DISTANCE] = "distance", 54 [IIO_DISTANCE] = "distance",
55 [IIO_VELOCITY] = "velocity", 55 [IIO_VELOCITY] = "velocity",
56 [IIO_CONCENTRATION] = "concentration",
57 [IIO_RESISTANCE] = "resistance",
58 [IIO_PH] = "ph",
59 [IIO_UVINDEX] = "uvindex",
56}; 60};
57 61
58static const char * const iio_ev_type_text[] = { 62static const char * const iio_ev_type_text[] = {
@@ -90,6 +94,7 @@ static const char * const iio_modifier_names[] = {
90 [IIO_MOD_LIGHT_RED] = "red", 94 [IIO_MOD_LIGHT_RED] = "red",
91 [IIO_MOD_LIGHT_GREEN] = "green", 95 [IIO_MOD_LIGHT_GREEN] = "green",
92 [IIO_MOD_LIGHT_BLUE] = "blue", 96 [IIO_MOD_LIGHT_BLUE] = "blue",
97 [IIO_MOD_LIGHT_UV] = "uv",
93 [IIO_MOD_QUATERNION] = "quaternion", 98 [IIO_MOD_QUATERNION] = "quaternion",
94 [IIO_MOD_TEMP_AMBIENT] = "ambient", 99 [IIO_MOD_TEMP_AMBIENT] = "ambient",
95 [IIO_MOD_TEMP_OBJECT] = "object", 100 [IIO_MOD_TEMP_OBJECT] = "object",
@@ -102,6 +107,10 @@ static const char * const iio_modifier_names[] = {
102 [IIO_MOD_WALKING] = "walking", 107 [IIO_MOD_WALKING] = "walking",
103 [IIO_MOD_STILL] = "still", 108 [IIO_MOD_STILL] = "still",
104 [IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)", 109 [IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)",
110 [IIO_MOD_I] = "i",
111 [IIO_MOD_Q] = "q",
112 [IIO_MOD_CO2] = "co2",
113 [IIO_MOD_VOC] = "voc",
105}; 114};
106 115
107static bool event_is_known(struct iio_event_data *event) 116static bool event_is_known(struct iio_event_data *event)
@@ -136,6 +145,10 @@ static bool event_is_known(struct iio_event_data *event)
136 case IIO_ENERGY: 145 case IIO_ENERGY:
137 case IIO_DISTANCE: 146 case IIO_DISTANCE:
138 case IIO_VELOCITY: 147 case IIO_VELOCITY:
148 case IIO_CONCENTRATION:
149 case IIO_RESISTANCE:
150 case IIO_PH:
151 case IIO_UVINDEX:
139 break; 152 break;
140 default: 153 default:
141 return false; 154 return false;
@@ -162,6 +175,7 @@ static bool event_is_known(struct iio_event_data *event)
162 case IIO_MOD_LIGHT_RED: 175 case IIO_MOD_LIGHT_RED:
163 case IIO_MOD_LIGHT_GREEN: 176 case IIO_MOD_LIGHT_GREEN:
164 case IIO_MOD_LIGHT_BLUE: 177 case IIO_MOD_LIGHT_BLUE:
178 case IIO_MOD_LIGHT_UV:
165 case IIO_MOD_QUATERNION: 179 case IIO_MOD_QUATERNION:
166 case IIO_MOD_TEMP_AMBIENT: 180 case IIO_MOD_TEMP_AMBIENT:
167 case IIO_MOD_TEMP_OBJECT: 181 case IIO_MOD_TEMP_OBJECT:
@@ -174,6 +188,10 @@ static bool event_is_known(struct iio_event_data *event)
174 case IIO_MOD_WALKING: 188 case IIO_MOD_WALKING:
175 case IIO_MOD_STILL: 189 case IIO_MOD_STILL:
176 case IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z: 190 case IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z:
191 case IIO_MOD_I:
192 case IIO_MOD_Q:
193 case IIO_MOD_CO2:
194 case IIO_MOD_VOC:
177 break; 195 break;
178 default: 196 default:
179 return false; 197 return false;
diff --git a/tools/iio/iio_utils.h b/tools/iio/iio_utils.h
index e3503bfe538b..780f2014f8fa 100644
--- a/tools/iio/iio_utils.h
+++ b/tools/iio/iio_utils.h
@@ -52,6 +52,13 @@ struct iio_channel_info {
52 unsigned location; 52 unsigned location;
53}; 53};
54 54
55static inline int iioutils_check_suffix(const char *str, const char *suffix)
56{
57 return strlen(str) >= strlen(suffix) &&
58 strncmp(str+strlen(str)-strlen(suffix),
59 suffix, strlen(suffix)) == 0;
60}
61
55int iioutils_break_up_name(const char *full_name, char **generic_name); 62int iioutils_break_up_name(const char *full_name, char **generic_name);
56int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used, 63int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
57 unsigned *shift, uint64_t *mask, unsigned *be, 64 unsigned *shift, uint64_t *mask, unsigned *be,
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 @@
1include ../../scripts/Makefile.include
2include ../../scripts/utilities.mak
3BINDIR=usr/bin
4MANDIR=usr/share/man
5MAN1DIR=$(MANDIR)/man1
6
7MAN1=kvm_stat.1
8
9A2X=a2x
10a2x_path := $(call get-executable,$(A2X))
11
12all: man
13
14ifneq ($(findstring $(MAKEFLAGS),s),s)
15 ifneq ($(V),1)
16 QUIET_A2X = @echo ' A2X '$@;
17 endif
18endif
19
20%.1: %.txt
21ifeq ($(a2x_path),)
22 $(error "You need to install asciidoc for man pages")
23else
24 $(QUIET_A2X)$(A2X) --doctype manpage --format manpage $<
25endif
26
27clean:
28 rm -f $(MAN1)
29
30man: $(MAN1)
31
32install-man: man
33 install -d -m 755 $(INSTALL_ROOT)/$(MAN1DIR)
34 install -m 644 kvm_stat.1 $(INSTALL_ROOT)/$(MAN1DIR)
35
36install-tools:
37 install -d -m 755 $(INSTALL_ROOT)/$(BINDIR)
38 install -m 755 -p "kvm_stat" "$(INSTALL_ROOT)/$(BINDIR)/$(TARGET)"
39
40install: 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
15Three 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
20The data is sampled from the KVM's debugfs entries and its perf events.
21"""
22
23import curses
24import sys
25import os
26import time
27import optparse
28import ctypes
29import fcntl
30import resource
31import struct
32import re
33from collections import defaultdict
34from time import sleep
35
36VMX_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
78SVM_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)
154AARCH64_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
193USERSPACE_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
221IOCTL_NUMBERS = {
222 'SET_FILTER': 0x40082406,
223 'ENABLE': 0x00002400,
224 'DISABLE': 0x00002401,
225 'RESET': 0x00002403,
226}
227
228class 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
258class 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
264class 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
278class 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
284class 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
290ARCH = Arch.get_arch()
291
292
293def 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
302def 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
319def 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
326def 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
342libc = ctypes.CDLL('libc.so.6', use_errno=True)
343syscall = libc.syscall
344
345class 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
373def 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
392PERF_TYPE_TRACEPOINT = 2
393PERF_FORMAT_GROUP = 1 << 3
394
395PATH_DEBUGFS_TRACING = '/sys/kernel/debug/tracing'
396PATH_DEBUGFS_KVM = '/sys/kernel/debug/kvm'
397
398class 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
430class 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
513class 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
653class 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
721class 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
789LABEL_WIDTH = 40
790NUMBER_WIDTH = 10
791
792class 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
963def 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
972def 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 print
979 def statline():
980 s = stats.get()
981 for k in keys:
982 print ' %9d' % s[k][1],
983 print
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
993def get_options():
994 """Returns processed program arguments."""
995 description_text = """
996This script displays various statistics about VMs running under KVM.
997The statistics are gathered from the KVM debugfs entries and / or the
998currently available perf traces.
999
1000The monitoring takes additional cpu cycles and might affect the VM's
1001performance.
1002
1003Requirements:
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
1063def 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
1076def 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
1105def 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
1126if __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 @@
1kvm_stat(1)
2===========
3
4NAME
5----
6kvm_stat - Report KVM kernel module event counters
7
8SYNOPSIS
9--------
10[verse]
11'kvm_stat' [OPTION]...
12
13DESCRIPTION
14-----------
15kvm_stat prints counts of KVM kernel module trace events. These events signify
16state transitions such as guest mode entry and exit.
17
18This tool is useful for observing guest behavior from the host perspective.
19Often conclusions about performance or buggy behavior can be drawn from the
20output.
21
22The set of KVM kernel module trace events may be specific to the kernel version
23or architecture. It is best to check the KVM kernel module source code for the
24meaning of events.
25
26OPTIONS
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
57SEE ALSO
58--------
59'perf'(1), 'trace-cmd'(1)
60
61AUTHOR
62------
63Stefan 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
30CFLAGS += -Wall -Werror $(EXTRA_WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES) 30CFLAGS += -Wall -Werror $(EXTRA_WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES)
31LDFLAGS += -lelf $(LIBSUBCMD) 31LDFLAGS += -lelf $(LIBSUBCMD)
32 32
33# Allow old libelf to be used:
34elfshdr := $(shell echo '\#include <libelf.h>' | $(CC) $(CFLAGS) -x c -E - | grep elf_getshdr)
35CFLAGS += $(if $(elfshdr),,-DLIBELF_USE_DEPRECATED)
36
33AWK = awk 37AWK = awk
34export srctree OUTPUT CFLAGS ARCH AWK 38export srctree OUTPUT CFLAGS ARCH AWK
35include $(srctree)/tools/build/Makefile.include 39include $(srctree)/tools/build/Makefile.include
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
26struct section { 31struct 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/arch/powerpc/include/perf_regs.h b/tools/perf/arch/powerpc/include/perf_regs.h
new file mode 100644
index 000000000000..75de0e92e71e
--- /dev/null
+++ b/tools/perf/arch/powerpc/include/perf_regs.h
@@ -0,0 +1,69 @@
1#ifndef ARCH_PERF_REGS_H
2#define ARCH_PERF_REGS_H
3
4#include <stdlib.h>
5#include <linux/types.h>
6#include <asm/perf_regs.h>
7
8#define PERF_REGS_MASK ((1ULL << PERF_REG_POWERPC_MAX) - 1)
9#define PERF_REGS_MAX PERF_REG_POWERPC_MAX
10#ifdef __powerpc64__
11 #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64
12#else
13 #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32
14#endif
15
16#define PERF_REG_IP PERF_REG_POWERPC_NIP
17#define PERF_REG_SP PERF_REG_POWERPC_R1
18
19static const char *reg_names[] = {
20 [PERF_REG_POWERPC_R0] = "r0",
21 [PERF_REG_POWERPC_R1] = "r1",
22 [PERF_REG_POWERPC_R2] = "r2",
23 [PERF_REG_POWERPC_R3] = "r3",
24 [PERF_REG_POWERPC_R4] = "r4",
25 [PERF_REG_POWERPC_R5] = "r5",
26 [PERF_REG_POWERPC_R6] = "r6",
27 [PERF_REG_POWERPC_R7] = "r7",
28 [PERF_REG_POWERPC_R8] = "r8",
29 [PERF_REG_POWERPC_R9] = "r9",
30 [PERF_REG_POWERPC_R10] = "r10",
31 [PERF_REG_POWERPC_R11] = "r11",
32 [PERF_REG_POWERPC_R12] = "r12",
33 [PERF_REG_POWERPC_R13] = "r13",
34 [PERF_REG_POWERPC_R14] = "r14",
35 [PERF_REG_POWERPC_R15] = "r15",
36 [PERF_REG_POWERPC_R16] = "r16",
37 [PERF_REG_POWERPC_R17] = "r17",
38 [PERF_REG_POWERPC_R18] = "r18",
39 [PERF_REG_POWERPC_R19] = "r19",
40 [PERF_REG_POWERPC_R20] = "r20",
41 [PERF_REG_POWERPC_R21] = "r21",
42 [PERF_REG_POWERPC_R22] = "r22",
43 [PERF_REG_POWERPC_R23] = "r23",
44 [PERF_REG_POWERPC_R24] = "r24",
45 [PERF_REG_POWERPC_R25] = "r25",
46 [PERF_REG_POWERPC_R26] = "r26",
47 [PERF_REG_POWERPC_R27] = "r27",
48 [PERF_REG_POWERPC_R28] = "r28",
49 [PERF_REG_POWERPC_R29] = "r29",
50 [PERF_REG_POWERPC_R30] = "r30",
51 [PERF_REG_POWERPC_R31] = "r31",
52 [PERF_REG_POWERPC_NIP] = "nip",
53 [PERF_REG_POWERPC_MSR] = "msr",
54 [PERF_REG_POWERPC_ORIG_R3] = "orig_r3",
55 [PERF_REG_POWERPC_CTR] = "ctr",
56 [PERF_REG_POWERPC_LINK] = "link",
57 [PERF_REG_POWERPC_XER] = "xer",
58 [PERF_REG_POWERPC_CCR] = "ccr",
59 [PERF_REG_POWERPC_SOFTE] = "softe",
60 [PERF_REG_POWERPC_TRAP] = "trap",
61 [PERF_REG_POWERPC_DAR] = "dar",
62 [PERF_REG_POWERPC_DSISR] = "dsisr"
63};
64
65static inline const char *perf_reg_name(int id)
66{
67 return reg_names[id];
68}
69#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build
index c8fe2074d217..90ad64b231cd 100644
--- a/tools/perf/arch/powerpc/util/Build
+++ b/tools/perf/arch/powerpc/util/Build
@@ -1,6 +1,8 @@
1libperf-y += header.o 1libperf-y += header.o
2libperf-y += sym-handling.o 2libperf-y += sym-handling.o
3libperf-y += kvm-stat.o 3libperf-y += kvm-stat.o
4libperf-y += perf_regs.o
4 5
5libperf-$(CONFIG_DWARF) += dwarf-regs.o 6libperf-$(CONFIG_DWARF) += dwarf-regs.o
6libperf-$(CONFIG_DWARF) += skip-callchain-idx.o 7libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
8libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
diff --git a/tools/perf/arch/powerpc/util/perf_regs.c b/tools/perf/arch/powerpc/util/perf_regs.c
new file mode 100644
index 000000000000..a3c3e1ce6807
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/perf_regs.c
@@ -0,0 +1,49 @@
1#include "../../perf.h"
2#include "../../util/perf_regs.h"
3
4const struct sample_reg sample_reg_masks[] = {
5 SMPL_REG(r0, PERF_REG_POWERPC_R0),
6 SMPL_REG(r1, PERF_REG_POWERPC_R1),
7 SMPL_REG(r2, PERF_REG_POWERPC_R2),
8 SMPL_REG(r3, PERF_REG_POWERPC_R3),
9 SMPL_REG(r4, PERF_REG_POWERPC_R4),
10 SMPL_REG(r5, PERF_REG_POWERPC_R5),
11 SMPL_REG(r6, PERF_REG_POWERPC_R6),
12 SMPL_REG(r7, PERF_REG_POWERPC_R7),
13 SMPL_REG(r8, PERF_REG_POWERPC_R8),
14 SMPL_REG(r9, PERF_REG_POWERPC_R9),
15 SMPL_REG(r10, PERF_REG_POWERPC_R10),
16 SMPL_REG(r11, PERF_REG_POWERPC_R11),
17 SMPL_REG(r12, PERF_REG_POWERPC_R12),
18 SMPL_REG(r13, PERF_REG_POWERPC_R13),
19 SMPL_REG(r14, PERF_REG_POWERPC_R14),
20 SMPL_REG(r15, PERF_REG_POWERPC_R15),
21 SMPL_REG(r16, PERF_REG_POWERPC_R16),
22 SMPL_REG(r17, PERF_REG_POWERPC_R17),
23 SMPL_REG(r18, PERF_REG_POWERPC_R18),
24 SMPL_REG(r19, PERF_REG_POWERPC_R19),
25 SMPL_REG(r20, PERF_REG_POWERPC_R20),
26 SMPL_REG(r21, PERF_REG_POWERPC_R21),
27 SMPL_REG(r22, PERF_REG_POWERPC_R22),
28 SMPL_REG(r23, PERF_REG_POWERPC_R23),
29 SMPL_REG(r24, PERF_REG_POWERPC_R24),
30 SMPL_REG(r25, PERF_REG_POWERPC_R25),
31 SMPL_REG(r26, PERF_REG_POWERPC_R26),
32 SMPL_REG(r27, PERF_REG_POWERPC_R27),
33 SMPL_REG(r28, PERF_REG_POWERPC_R28),
34 SMPL_REG(r29, PERF_REG_POWERPC_R29),
35 SMPL_REG(r30, PERF_REG_POWERPC_R30),
36 SMPL_REG(r31, PERF_REG_POWERPC_R31),
37 SMPL_REG(nip, PERF_REG_POWERPC_NIP),
38 SMPL_REG(msr, PERF_REG_POWERPC_MSR),
39 SMPL_REG(orig_r3, PERF_REG_POWERPC_ORIG_R3),
40 SMPL_REG(ctr, PERF_REG_POWERPC_CTR),
41 SMPL_REG(link, PERF_REG_POWERPC_LINK),
42 SMPL_REG(xer, PERF_REG_POWERPC_XER),
43 SMPL_REG(ccr, PERF_REG_POWERPC_CCR),
44 SMPL_REG(softe, PERF_REG_POWERPC_SOFTE),
45 SMPL_REG(trap, PERF_REG_POWERPC_TRAP),
46 SMPL_REG(dar, PERF_REG_POWERPC_DAR),
47 SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
48 SMPL_REG_END
49};
diff --git a/tools/perf/arch/powerpc/util/unwind-libunwind.c b/tools/perf/arch/powerpc/util/unwind-libunwind.c
new file mode 100644
index 000000000000..9e15f92ae49f
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/unwind-libunwind.c
@@ -0,0 +1,96 @@
1/*
2 * Copyright 2016 Chandan Kumar, IBM Corporation.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include <errno.h>
11#include <libunwind.h>
12#include <asm/perf_regs.h>
13#include "../../util/unwind.h"
14#include "../../util/debug.h"
15
16int libunwind__arch_reg_id(int regnum)
17{
18 switch (regnum) {
19 case UNW_PPC64_R0:
20 return PERF_REG_POWERPC_R0;
21 case UNW_PPC64_R1:
22 return PERF_REG_POWERPC_R1;
23 case UNW_PPC64_R2:
24 return PERF_REG_POWERPC_R2;
25 case UNW_PPC64_R3:
26 return PERF_REG_POWERPC_R3;
27 case UNW_PPC64_R4:
28 return PERF_REG_POWERPC_R4;
29 case UNW_PPC64_R5:
30 return PERF_REG_POWERPC_R5;
31 case UNW_PPC64_R6:
32 return PERF_REG_POWERPC_R6;
33 case UNW_PPC64_R7:
34 return PERF_REG_POWERPC_R7;
35 case UNW_PPC64_R8:
36 return PERF_REG_POWERPC_R8;
37 case UNW_PPC64_R9:
38 return PERF_REG_POWERPC_R9;
39 case UNW_PPC64_R10:
40 return PERF_REG_POWERPC_R10;
41 case UNW_PPC64_R11:
42 return PERF_REG_POWERPC_R11;
43 case UNW_PPC64_R12:
44 return PERF_REG_POWERPC_R12;
45 case UNW_PPC64_R13:
46 return PERF_REG_POWERPC_R13;
47 case UNW_PPC64_R14:
48 return PERF_REG_POWERPC_R14;
49 case UNW_PPC64_R15:
50 return PERF_REG_POWERPC_R15;
51 case UNW_PPC64_R16:
52 return PERF_REG_POWERPC_R16;
53 case UNW_PPC64_R17:
54 return PERF_REG_POWERPC_R17;
55 case UNW_PPC64_R18:
56 return PERF_REG_POWERPC_R18;
57 case UNW_PPC64_R19:
58 return PERF_REG_POWERPC_R19;
59 case UNW_PPC64_R20:
60 return PERF_REG_POWERPC_R20;
61 case UNW_PPC64_R21:
62 return PERF_REG_POWERPC_R21;
63 case UNW_PPC64_R22:
64 return PERF_REG_POWERPC_R22;
65 case UNW_PPC64_R23:
66 return PERF_REG_POWERPC_R23;
67 case UNW_PPC64_R24:
68 return PERF_REG_POWERPC_R24;
69 case UNW_PPC64_R25:
70 return PERF_REG_POWERPC_R25;
71 case UNW_PPC64_R26:
72 return PERF_REG_POWERPC_R26;
73 case UNW_PPC64_R27:
74 return PERF_REG_POWERPC_R27;
75 case UNW_PPC64_R28:
76 return PERF_REG_POWERPC_R28;
77 case UNW_PPC64_R29:
78 return PERF_REG_POWERPC_R29;
79 case UNW_PPC64_R30:
80 return PERF_REG_POWERPC_R30;
81 case UNW_PPC64_R31:
82 return PERF_REG_POWERPC_R31;
83 case UNW_PPC64_LR:
84 return PERF_REG_POWERPC_LINK;
85 case UNW_PPC64_CTR:
86 return PERF_REG_POWERPC_CTR;
87 case UNW_PPC64_XER:
88 return PERF_REG_POWERPC_XER;
89 case UNW_PPC64_NIP:
90 return PERF_REG_POWERPC_NIP;
91 default:
92 pr_err("unwind: invalid reg id %d\n", regnum);
93 return -EINVAL;
94 }
95 return -EINVAL;
96}
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
45struct record { 46struct 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
86static int
87backward_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
120static int
121rb_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
85static int record__mmap_read(struct record *rec, int idx) 134static 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);
124out: 185out:
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
873static int syscall_fmt__cmp(const void *name, const void *fmtp) 796static 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
1086static 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
1163static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) 1104static 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)
1186static int syscall__set_arg_fmts(struct syscall *sc) 1127static 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/config/Makefile b/tools/perf/config/Makefile
index 1e46277286c2..5ad0255f8756 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -23,6 +23,12 @@ $(call detected_var,ARCH)
23 23
24NO_PERF_REGS := 1 24NO_PERF_REGS := 1
25 25
26# Additional ARCH settings for ppc
27ifeq ($(ARCH),powerpc)
28 NO_PERF_REGS := 0
29 LIBUNWIND_LIBS := -lunwind -lunwind-ppc64
30endif
31
26# Additional ARCH settings for x86 32# Additional ARCH settings for x86
27ifeq ($(ARCH),x86) 33ifeq ($(ARCH),x86)
28 $(call detected,CONFIG_X86) 34 $(call detected,CONFIG_X86)
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/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index 53c2273e8859..ad1cb63139a7 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -73,7 +73,7 @@ int test__openat_syscall_event_on_all_cpus(int subtest __maybe_unused)
73 } 73 }
74 74
75 /* 75 /*
76 * Here we need to explicitely preallocate the counts, as if 76 * Here we need to explicitly preallocate the counts, as if
77 * we use the auto allocation it will allocate just for 1 cpu, 77 * we use the auto allocation it will allocate just for 1 cpu,
78 * as we start by cpu 0. 78 * as we start by cpu 0.
79 */ 79 */
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 */
360static struct ins instructions[] = { 357static 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
452static int ins__cmp(const void *name, const void *insp) 449static 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
456static 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
464static void ins__sort(void)
465{
466 const int nmemb = ARRAY_SIZE(instructions);
467
468 qsort(instructions, nmemb, sizeof(struct ins), ins__cmp);
469}
470
459static struct ins *ins__find(const char *name) 471static 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
466int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym) 484int 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);
1128fallback: 1146fallback:
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/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
11char dso__symtab_origin(const struct dso *dso) 12char 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/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
49struct perf_evlist *perf_evlist__new(void) 50struct 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
683static 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
700int perf_evlist__pause(struct perf_evlist *evlist)
701{
702 return perf_evlist__set_paused(evlist, true);
703}
704
705int 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 */
683static union perf_event * 711static union perf_event *
684perf_mmap__read(struct perf_mmap *md, bool check_messup, u64 start, 712perf_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
902static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 931static 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;
28struct perf_mmap { 28struct 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
136void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); 138void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
137 139
140int perf_evlist__pause(struct perf_evlist *evlist);
141int perf_evlist__resume(struct perf_evlist *evlist);
138int perf_evlist__open(struct perf_evlist *evlist); 142int perf_evlist__open(struct perf_evlist *evlist);
139void perf_evlist__close(struct perf_evlist *evlist); 143void perf_evlist__close(struct perf_evlist *evlist);
140 144
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 964c7c3602c0..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
42static clockid_t clockid; 43static clockid_t clockid;
@@ -827,7 +828,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
827 perf_evsel__set_sample_bit(evsel, PERIOD); 828 perf_evsel__set_sample_bit(evsel, PERIOD);
828 829
829 /* 830 /*
830 * When the user explicitely disabled time don't force it here. 831 * When the user explicitly disabled time don't force it here.
831 */ 832 */
832 if (opts->sample_time && 833 if (opts->sample_time &&
833 (!perf_missing_features.sample_id_all && 834 (!perf_missing_features.sample_id_all &&
@@ -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;
1379retry_sample_id: 1382retry_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
1505out_close: 1518out_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 639a2903065e..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
@@ -362,7 +363,7 @@ out_err:
362} 363}
363 364
364/* 365/*
365 * Caller must eventually drop thread->refcnt returned with a successfull 366 * Caller must eventually drop thread->refcnt returned with a successful
366 * lookup/new thread inserted. 367 * lookup/new thread inserted.
367 */ 368 */
368static struct thread *____machine__findnew_thread(struct machine *machine, 369static struct thread *____machine__findnew_thread(struct machine *machine,
@@ -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
1891check_calls: 1887check_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/parse-events.c b/tools/perf/util/parse-events.c
index bcbc983d4b12..c6fd0479f4cd 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1649,7 +1649,7 @@ static void parse_events_print_error(struct parse_events_error *err,
1649 1649
1650 buf = _buf; 1650 buf = _buf;
1651 1651
1652 /* We're cutting from the beggining. */ 1652 /* We're cutting from the beginning. */
1653 if (err->idx > max_err_idx) 1653 if (err->idx > max_err_idx)
1654 cut = err->idx - max_err_idx; 1654 cut = err->idx - max_err_idx;
1655 1655
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index 6b8eb13e14e4..c4023f22f287 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -12,18 +12,18 @@ int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
12 int i, idx = 0; 12 int i, idx = 0;
13 u64 mask = regs->mask; 13 u64 mask = regs->mask;
14 14
15 if (regs->cache_mask & (1 << id)) 15 if (regs->cache_mask & (1ULL << id))
16 goto out; 16 goto out;
17 17
18 if (!(mask & (1 << id))) 18 if (!(mask & (1ULL << id)))
19 return -EINVAL; 19 return -EINVAL;
20 20
21 for (i = 0; i < id; i++) { 21 for (i = 0; i < id; i++) {
22 if (mask & (1 << i)) 22 if (mask & (1ULL << i))
23 idx++; 23 idx++;
24 } 24 }
25 25
26 regs->cache_mask |= (1 << id); 26 regs->cache_mask |= (1ULL << id);
27 regs->cache_regs[id] = regs->regs[idx]; 27 regs->cache_regs[id] = regs->regs[idx];
28 28
29out: 29out:
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/session.c b/tools/perf/util/session.c
index 2335b2824d8a..5214974e841a 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -557,7 +557,7 @@ static u8 revbyte(u8 b)
557 557
558/* 558/*
559 * XXX this is hack in attempt to carry flags bitfield 559 * XXX this is hack in attempt to carry flags bitfield
560 * throught endian village. ABI says: 560 * through endian village. ABI says:
561 * 561 *
562 * Bit-fields are allocated from right to left (least to most significant) 562 * Bit-fields are allocated from right to left (least to most significant)
563 * on little-endian implementations and from left to right (most to least 563 * on little-endian implementations and from left to right (most to least
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
358static int64_t
359sort__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
384static 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
390struct 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
399static int64_t
400sort__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
425static 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
431struct 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
358static char no_srcfile[1]; 440static 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
194static void print_branch_misses(int cpu, 195static 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..20f9cb32b703 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 }
@@ -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
2037int 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
188struct mem_info { 193struct mem_info {
@@ -287,6 +292,8 @@ bool symbol_type__is_a(char symbol_type, enum map_type map_type);
287bool symbol__restricted_filename(const char *filename, 292bool symbol__restricted_filename(const char *filename,
288 const char *restricted_filename); 293 const char *restricted_filename);
289bool symbol__is_idle(struct symbol *sym); 294bool symbol__is_idle(struct symbol *sym);
295int symbol__config_symfs(const struct option *opt __maybe_unused,
296 const char *dir, int unset __maybe_unused);
290 297
291int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, 298int 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 = {
33unsigned int page_size; 33unsigned int page_size;
34int cacheline_size; 34int cacheline_size;
35 35
36unsigned int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH; 36int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH;
37int sysctl_perf_event_max_contexts_per_stack = PERF_MAX_CONTEXTS_PER_STACK;
37 38
38bool test_attr__enabled; 39bool 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
262extern unsigned int page_size; 262extern unsigned int page_size;
263extern int cacheline_size; 263extern int cacheline_size;
264extern unsigned int sysctl_perf_event_max_stack; 264extern int sysctl_perf_event_max_stack;
265extern int sysctl_perf_event_max_contexts_per_stack;
265 266
266struct parse_tag { 267struct parse_tag {
267 char tag; 268 char tag;
diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild
index a34bfd0c8928..785985677159 100644
--- a/tools/testing/nvdimm/Kbuild
+++ b/tools/testing/nvdimm/Kbuild
@@ -7,6 +7,7 @@ ldflags-y += --wrap=ioremap_nocache
7ldflags-y += --wrap=iounmap 7ldflags-y += --wrap=iounmap
8ldflags-y += --wrap=memunmap 8ldflags-y += --wrap=memunmap
9ldflags-y += --wrap=__devm_request_region 9ldflags-y += --wrap=__devm_request_region
10ldflags-y += --wrap=__devm_release_region
10ldflags-y += --wrap=__request_region 11ldflags-y += --wrap=__request_region
11ldflags-y += --wrap=__release_region 12ldflags-y += --wrap=__release_region
12ldflags-y += --wrap=devm_memremap_pages 13ldflags-y += --wrap=devm_memremap_pages
@@ -15,6 +16,7 @@ ldflags-y += --wrap=phys_to_pfn_t
15DRIVERS := ../../../drivers 16DRIVERS := ../../../drivers
16NVDIMM_SRC := $(DRIVERS)/nvdimm 17NVDIMM_SRC := $(DRIVERS)/nvdimm
17ACPI_SRC := $(DRIVERS)/acpi 18ACPI_SRC := $(DRIVERS)/acpi
19DAX_SRC := $(DRIVERS)/dax
18 20
19obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o 21obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o
20obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o 22obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
@@ -22,6 +24,8 @@ obj-$(CONFIG_ND_BTT) += nd_btt.o
22obj-$(CONFIG_ND_BLK) += nd_blk.o 24obj-$(CONFIG_ND_BLK) += nd_blk.o
23obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o 25obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o
24obj-$(CONFIG_ACPI_NFIT) += nfit.o 26obj-$(CONFIG_ACPI_NFIT) += nfit.o
27obj-$(CONFIG_DEV_DAX) += dax.o
28obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o
25 29
26nfit-y := $(ACPI_SRC)/nfit.o 30nfit-y := $(ACPI_SRC)/nfit.o
27nfit-y += config_check.o 31nfit-y += config_check.o
@@ -38,6 +42,12 @@ nd_blk-y += config_check.o
38nd_e820-y := $(NVDIMM_SRC)/e820.o 42nd_e820-y := $(NVDIMM_SRC)/e820.o
39nd_e820-y += config_check.o 43nd_e820-y += config_check.o
40 44
45dax-y := $(DAX_SRC)/dax.o
46dax-y += config_check.o
47
48dax_pmem-y := $(DAX_SRC)/pmem.o
49dax_pmem-y += config_check.o
50
41libnvdimm-y := $(NVDIMM_SRC)/core.o 51libnvdimm-y := $(NVDIMM_SRC)/core.o
42libnvdimm-y += $(NVDIMM_SRC)/bus.o 52libnvdimm-y += $(NVDIMM_SRC)/bus.o
43libnvdimm-y += $(NVDIMM_SRC)/dimm_devs.o 53libnvdimm-y += $(NVDIMM_SRC)/dimm_devs.o
@@ -49,6 +59,7 @@ libnvdimm-y += $(NVDIMM_SRC)/label.o
49libnvdimm-$(CONFIG_ND_CLAIM) += $(NVDIMM_SRC)/claim.o 59libnvdimm-$(CONFIG_ND_CLAIM) += $(NVDIMM_SRC)/claim.o
50libnvdimm-$(CONFIG_BTT) += $(NVDIMM_SRC)/btt_devs.o 60libnvdimm-$(CONFIG_BTT) += $(NVDIMM_SRC)/btt_devs.o
51libnvdimm-$(CONFIG_NVDIMM_PFN) += $(NVDIMM_SRC)/pfn_devs.o 61libnvdimm-$(CONFIG_NVDIMM_PFN) += $(NVDIMM_SRC)/pfn_devs.o
62libnvdimm-$(CONFIG_NVDIMM_DAX) += $(NVDIMM_SRC)/dax_devs.o
52libnvdimm-y += config_check.o 63libnvdimm-y += config_check.o
53 64
54obj-m += test/ 65obj-m += test/
diff --git a/tools/testing/nvdimm/config_check.c b/tools/testing/nvdimm/config_check.c
index f2c7615554eb..adf18bfeca00 100644
--- a/tools/testing/nvdimm/config_check.c
+++ b/tools/testing/nvdimm/config_check.c
@@ -12,4 +12,6 @@ void check(void)
12 BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BTT)); 12 BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BTT));
13 BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BLK)); 13 BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BLK));
14 BUILD_BUG_ON(!IS_MODULE(CONFIG_ACPI_NFIT)); 14 BUILD_BUG_ON(!IS_MODULE(CONFIG_ACPI_NFIT));
15 BUILD_BUG_ON(!IS_MODULE(CONFIG_DEV_DAX));
16 BUILD_BUG_ON(!IS_MODULE(CONFIG_DEV_DAX_PMEM));
15} 17}
diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c
index 0c1a7e65bb81..c842095f2801 100644
--- a/tools/testing/nvdimm/test/iomap.c
+++ b/tools/testing/nvdimm/test/iomap.c
@@ -239,13 +239,11 @@ struct resource *__wrap___devm_request_region(struct device *dev,
239} 239}
240EXPORT_SYMBOL(__wrap___devm_request_region); 240EXPORT_SYMBOL(__wrap___devm_request_region);
241 241
242void __wrap___release_region(struct resource *parent, resource_size_t start, 242static bool nfit_test_release_region(struct resource *parent,
243 resource_size_t n) 243 resource_size_t start, resource_size_t n)
244{ 244{
245 struct nfit_test_resource *nfit_res;
246
247 if (parent == &iomem_resource) { 245 if (parent == &iomem_resource) {
248 nfit_res = get_nfit_res(start); 246 struct nfit_test_resource *nfit_res = get_nfit_res(start);
249 if (nfit_res) { 247 if (nfit_res) {
250 struct resource *res = nfit_res->res + 1; 248 struct resource *res = nfit_res->res + 1;
251 249
@@ -254,11 +252,26 @@ void __wrap___release_region(struct resource *parent, resource_size_t start,
254 __func__, start, n, res); 252 __func__, start, n, res);
255 else 253 else
256 memset(res, 0, sizeof(*res)); 254 memset(res, 0, sizeof(*res));
257 return; 255 return true;
258 } 256 }
259 } 257 }
260 __release_region(parent, start, n); 258 return false;
259}
260
261void __wrap___release_region(struct resource *parent, resource_size_t start,
262 resource_size_t n)
263{
264 if (!nfit_test_release_region(parent, start, n))
265 __release_region(parent, start, n);
261} 266}
262EXPORT_SYMBOL(__wrap___release_region); 267EXPORT_SYMBOL(__wrap___release_region);
263 268
269void __wrap___devm_release_region(struct device *dev, struct resource *parent,
270 resource_size_t start, resource_size_t n)
271{
272 if (!nfit_test_release_region(parent, start, n))
273 __devm_release_region(dev, parent, start, n);
274}
275EXPORT_SYMBOL(__wrap___devm_release_region);
276
264MODULE_LICENSE("GPL v2"); 277MODULE_LICENSE("GPL v2");
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 3187322eeed7..c919866853a0 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -330,12 +330,49 @@ static int nfit_test_cmd_clear_error(struct nd_cmd_clear_error *clear_err,
330 return 0; 330 return 0;
331} 331}
332 332
333static int nfit_test_cmd_smart(struct nd_cmd_smart *smart, unsigned int buf_len)
334{
335 static const struct nd_smart_payload smart_data = {
336 .flags = ND_SMART_HEALTH_VALID | ND_SMART_TEMP_VALID
337 | ND_SMART_SPARES_VALID | ND_SMART_ALARM_VALID
338 | ND_SMART_USED_VALID | ND_SMART_SHUTDOWN_VALID,
339 .health = ND_SMART_NON_CRITICAL_HEALTH,
340 .temperature = 23 * 16,
341 .spares = 75,
342 .alarm_flags = ND_SMART_SPARE_TRIP | ND_SMART_TEMP_TRIP,
343 .life_used = 5,
344 .shutdown_state = 0,
345 .vendor_size = 0,
346 };
347
348 if (buf_len < sizeof(*smart))
349 return -EINVAL;
350 memcpy(smart->data, &smart_data, sizeof(smart_data));
351 return 0;
352}
353
354static int nfit_test_cmd_smart_threshold(struct nd_cmd_smart_threshold *smart_t,
355 unsigned int buf_len)
356{
357 static const struct nd_smart_threshold_payload smart_t_data = {
358 .alarm_control = ND_SMART_SPARE_TRIP | ND_SMART_TEMP_TRIP,
359 .temperature = 40 * 16,
360 .spares = 5,
361 };
362
363 if (buf_len < sizeof(*smart_t))
364 return -EINVAL;
365 memcpy(smart_t->data, &smart_t_data, sizeof(smart_t_data));
366 return 0;
367}
368
333static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, 369static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
334 struct nvdimm *nvdimm, unsigned int cmd, void *buf, 370 struct nvdimm *nvdimm, unsigned int cmd, void *buf,
335 unsigned int buf_len, int *cmd_rc) 371 unsigned int buf_len, int *cmd_rc)
336{ 372{
337 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); 373 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
338 struct nfit_test *t = container_of(acpi_desc, typeof(*t), acpi_desc); 374 struct nfit_test *t = container_of(acpi_desc, typeof(*t), acpi_desc);
375 unsigned int func = cmd;
339 int i, rc = 0, __cmd_rc; 376 int i, rc = 0, __cmd_rc;
340 377
341 if (!cmd_rc) 378 if (!cmd_rc)
@@ -344,8 +381,23 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
344 381
345 if (nvdimm) { 382 if (nvdimm) {
346 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); 383 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
384 unsigned long cmd_mask = nvdimm_cmd_mask(nvdimm);
347 385
348 if (!nfit_mem || !test_bit(cmd, &nfit_mem->dsm_mask)) 386 if (!nfit_mem)
387 return -ENOTTY;
388
389 if (cmd == ND_CMD_CALL) {
390 struct nd_cmd_pkg *call_pkg = buf;
391
392 buf_len = call_pkg->nd_size_in + call_pkg->nd_size_out;
393 buf = (void *) call_pkg->nd_payload;
394 func = call_pkg->nd_command;
395 if (call_pkg->nd_family != nfit_mem->family)
396 return -ENOTTY;
397 }
398
399 if (!test_bit(cmd, &cmd_mask)
400 || !test_bit(func, &nfit_mem->dsm_mask))
349 return -ENOTTY; 401 return -ENOTTY;
350 402
351 /* lookup label space for the given dimm */ 403 /* lookup label space for the given dimm */
@@ -356,7 +408,7 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
356 if (i >= ARRAY_SIZE(handle)) 408 if (i >= ARRAY_SIZE(handle))
357 return -ENXIO; 409 return -ENXIO;
358 410
359 switch (cmd) { 411 switch (func) {
360 case ND_CMD_GET_CONFIG_SIZE: 412 case ND_CMD_GET_CONFIG_SIZE:
361 rc = nfit_test_cmd_get_config_size(buf, buf_len); 413 rc = nfit_test_cmd_get_config_size(buf, buf_len);
362 break; 414 break;
@@ -368,16 +420,22 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
368 rc = nfit_test_cmd_set_config_data(buf, buf_len, 420 rc = nfit_test_cmd_set_config_data(buf, buf_len,
369 t->label[i]); 421 t->label[i]);
370 break; 422 break;
423 case ND_CMD_SMART:
424 rc = nfit_test_cmd_smart(buf, buf_len);
425 break;
426 case ND_CMD_SMART_THRESHOLD:
427 rc = nfit_test_cmd_smart_threshold(buf, buf_len);
428 break;
371 default: 429 default:
372 return -ENOTTY; 430 return -ENOTTY;
373 } 431 }
374 } else { 432 } else {
375 struct ars_state *ars_state = &t->ars_state; 433 struct ars_state *ars_state = &t->ars_state;
376 434
377 if (!nd_desc || !test_bit(cmd, &nd_desc->dsm_mask)) 435 if (!nd_desc || !test_bit(cmd, &nd_desc->cmd_mask))
378 return -ENOTTY; 436 return -ENOTTY;
379 437
380 switch (cmd) { 438 switch (func) {
381 case ND_CMD_ARS_CAP: 439 case ND_CMD_ARS_CAP:
382 rc = nfit_test_cmd_ars_cap(buf, buf_len); 440 rc = nfit_test_cmd_ars_cap(buf, buf_len);
383 break; 441 break;
@@ -1251,13 +1309,15 @@ static void nfit_test0_setup(struct nfit_test *t)
1251 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA0_SIZE); 1309 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA0_SIZE);
1252 1310
1253 acpi_desc = &t->acpi_desc; 1311 acpi_desc = &t->acpi_desc;
1254 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en); 1312 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en);
1255 set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); 1313 set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
1256 set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); 1314 set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
1257 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en); 1315 set_bit(ND_CMD_SMART, &acpi_desc->dimm_cmd_force_en);
1258 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en); 1316 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en);
1259 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_dsm_force_en); 1317 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
1260 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_dsm_force_en); 1318 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
1319 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
1320 set_bit(ND_CMD_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
1261} 1321}
1262 1322
1263static void nfit_test1_setup(struct nfit_test *t) 1323static void nfit_test1_setup(struct nfit_test *t)
@@ -1315,10 +1375,10 @@ static void nfit_test1_setup(struct nfit_test *t)
1315 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA2_SIZE); 1375 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA2_SIZE);
1316 1376
1317 acpi_desc = &t->acpi_desc; 1377 acpi_desc = &t->acpi_desc;
1318 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en); 1378 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en);
1319 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en); 1379 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
1320 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_dsm_force_en); 1380 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
1321 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_dsm_force_en); 1381 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
1322} 1382}
1323 1383
1324static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa, 1384static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile
index 604212db9d4b..3b530467148e 100644
--- a/tools/testing/radix-tree/Makefile
+++ b/tools/testing/radix-tree/Makefile
@@ -3,7 +3,7 @@ CFLAGS += -I. -g -Wall -D_LGPL_SOURCE
3LDFLAGS += -lpthread -lurcu 3LDFLAGS += -lpthread -lurcu
4TARGETS = main 4TARGETS = main
5OFILES = main.o radix-tree.o linux.o test.o tag_check.o find_next_bit.o \ 5OFILES = main.o radix-tree.o linux.o test.o tag_check.o find_next_bit.o \
6 regression1.o regression2.o regression3.o 6 regression1.o regression2.o regression3.o multiorder.o
7 7
8targets: $(TARGETS) 8targets: $(TARGETS)
9 9
@@ -13,7 +13,7 @@ main: $(OFILES)
13clean: 13clean:
14 $(RM) -f $(TARGETS) *.o radix-tree.c 14 $(RM) -f $(TARGETS) *.o radix-tree.c
15 15
16$(OFILES): *.h */*.h 16$(OFILES): *.h */*.h ../../../include/linux/radix-tree.h ../../include/linux/*.h
17 17
18radix-tree.c: ../../../lib/radix-tree.c 18radix-tree.c: ../../../lib/radix-tree.c
19 sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@ 19 sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@
diff --git a/tools/testing/radix-tree/generated/autoconf.h b/tools/testing/radix-tree/generated/autoconf.h
new file mode 100644
index 000000000000..ad18cf5a2a3a
--- /dev/null
+++ b/tools/testing/radix-tree/generated/autoconf.h
@@ -0,0 +1,3 @@
1#define CONFIG_RADIX_TREE_MULTIORDER 1
2#define CONFIG_SHMEM 1
3#define CONFIG_SWAP 1
diff --git a/tools/testing/radix-tree/linux/init.h b/tools/testing/radix-tree/linux/init.h
new file mode 100644
index 000000000000..360cabb3c4e7
--- /dev/null
+++ b/tools/testing/radix-tree/linux/init.h
@@ -0,0 +1 @@
/* An empty file stub that allows radix-tree.c to compile. */
diff --git a/tools/testing/radix-tree/linux/kernel.h b/tools/testing/radix-tree/linux/kernel.h
index ae013b0160ac..be98a47b4e1b 100644
--- a/tools/testing/radix-tree/linux/kernel.h
+++ b/tools/testing/radix-tree/linux/kernel.h
@@ -7,19 +7,28 @@
7#include <stddef.h> 7#include <stddef.h>
8#include <limits.h> 8#include <limits.h>
9 9
10#include "../../include/linux/compiler.h"
11#include "../../../include/linux/kconfig.h"
12
13#define RADIX_TREE_MAP_SHIFT 3
14
10#ifndef NULL 15#ifndef NULL
11#define NULL 0 16#define NULL 0
12#endif 17#endif
13 18
14#define BUG_ON(expr) assert(!(expr)) 19#define BUG_ON(expr) assert(!(expr))
20#define WARN_ON(expr) assert(!(expr))
15#define __init 21#define __init
16#define __must_check 22#define __must_check
17#define panic(expr) 23#define panic(expr)
18#define printk printf 24#define printk printf
19#define __force 25#define __force
20#define likely(c) (c)
21#define unlikely(c) (c)
22#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) 26#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
27#define pr_debug printk
28
29#define smp_rmb() barrier()
30#define smp_wmb() barrier()
31#define cpu_relax() barrier()
23 32
24#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 33#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
25 34
@@ -28,6 +37,8 @@
28 (type *)( (char *)__mptr - offsetof(type, member) );}) 37 (type *)( (char *)__mptr - offsetof(type, member) );})
29#define min(a, b) ((a) < (b) ? (a) : (b)) 38#define min(a, b) ((a) < (b) ? (a) : (b))
30 39
40#define cond_resched() sched_yield()
41
31static inline int in_interrupt(void) 42static inline int in_interrupt(void)
32{ 43{
33 return 0; 44 return 0;
diff --git a/tools/testing/radix-tree/linux/slab.h b/tools/testing/radix-tree/linux/slab.h
index 57282506c21d..6d5a34770fd4 100644
--- a/tools/testing/radix-tree/linux/slab.h
+++ b/tools/testing/radix-tree/linux/slab.h
@@ -3,7 +3,6 @@
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5 5
6#define GFP_KERNEL 1
7#define SLAB_HWCACHE_ALIGN 1 6#define SLAB_HWCACHE_ALIGN 1
8#define SLAB_PANIC 2 7#define SLAB_PANIC 2
9#define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* Objects are reclaimable */ 8#define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* Objects are reclaimable */
diff --git a/tools/testing/radix-tree/linux/types.h b/tools/testing/radix-tree/linux/types.h
index 72a9d85f6c76..faa0b6ff9ca8 100644
--- a/tools/testing/radix-tree/linux/types.h
+++ b/tools/testing/radix-tree/linux/types.h
@@ -1,15 +1,13 @@
1#ifndef _TYPES_H 1#ifndef _TYPES_H
2#define _TYPES_H 2#define _TYPES_H
3 3
4#include "../../include/linux/types.h"
5
4#define __rcu 6#define __rcu
5#define __read_mostly 7#define __read_mostly
6 8
7#define BITS_PER_LONG (sizeof(long) * 8) 9#define BITS_PER_LONG (sizeof(long) * 8)
8 10
9struct list_head {
10 struct list_head *next, *prev;
11};
12
13static inline void INIT_LIST_HEAD(struct list_head *list) 11static inline void INIT_LIST_HEAD(struct list_head *list)
14{ 12{
15 list->next = list; 13 list->next = list;
@@ -22,7 +20,6 @@ typedef struct {
22 20
23#define uninitialized_var(x) x = x 21#define uninitialized_var(x) x = x
24 22
25typedef unsigned gfp_t;
26#include <linux/gfp.h> 23#include <linux/gfp.h>
27 24
28#endif 25#endif
diff --git a/tools/testing/radix-tree/main.c b/tools/testing/radix-tree/main.c
index 0e83cad27a9f..b7619ff3b552 100644
--- a/tools/testing/radix-tree/main.c
+++ b/tools/testing/radix-tree/main.c
@@ -61,11 +61,11 @@ void __big_gang_check(void)
61 } while (!wrapped); 61 } while (!wrapped);
62} 62}
63 63
64void big_gang_check(void) 64void big_gang_check(bool long_run)
65{ 65{
66 int i; 66 int i;
67 67
68 for (i = 0; i < 1000; i++) { 68 for (i = 0; i < (long_run ? 1000 : 3); i++) {
69 __big_gang_check(); 69 __big_gang_check();
70 srand(time(0)); 70 srand(time(0));
71 printf("%d ", i); 71 printf("%d ", i);
@@ -232,10 +232,72 @@ void copy_tag_check(void)
232 item_kill_tree(&tree); 232 item_kill_tree(&tree);
233} 233}
234 234
235static void single_thread_tests(void) 235static void __locate_check(struct radix_tree_root *tree, unsigned long index,
236 unsigned order)
237{
238 struct item *item;
239 unsigned long index2;
240
241 item_insert_order(tree, index, order);
242 item = item_lookup(tree, index);
243 index2 = radix_tree_locate_item(tree, item);
244 if (index != index2) {
245 printf("index %ld order %d inserted; found %ld\n",
246 index, order, index2);
247 abort();
248 }
249}
250
251static void __order_0_locate_check(void)
252{
253 RADIX_TREE(tree, GFP_KERNEL);
254 int i;
255
256 for (i = 0; i < 50; i++)
257 __locate_check(&tree, rand() % INT_MAX, 0);
258
259 item_kill_tree(&tree);
260}
261
262static void locate_check(void)
263{
264 RADIX_TREE(tree, GFP_KERNEL);
265 unsigned order;
266 unsigned long offset, index;
267
268 __order_0_locate_check();
269
270 for (order = 0; order < 20; order++) {
271 for (offset = 0; offset < (1 << (order + 3));
272 offset += (1UL << order)) {
273 for (index = 0; index < (1UL << (order + 5));
274 index += (1UL << order)) {
275 __locate_check(&tree, index + offset, order);
276 }
277 if (radix_tree_locate_item(&tree, &tree) != -1)
278 abort();
279
280 item_kill_tree(&tree);
281 }
282 }
283
284 if (radix_tree_locate_item(&tree, &tree) != -1)
285 abort();
286 __locate_check(&tree, -1, 0);
287 if (radix_tree_locate_item(&tree, &tree) != -1)
288 abort();
289 item_kill_tree(&tree);
290}
291
292static void single_thread_tests(bool long_run)
236{ 293{
237 int i; 294 int i;
238 295
296 printf("starting single_thread_tests: %d allocated\n", nr_allocated);
297 multiorder_checks();
298 printf("after multiorder_check: %d allocated\n", nr_allocated);
299 locate_check();
300 printf("after locate_check: %d allocated\n", nr_allocated);
239 tag_check(); 301 tag_check();
240 printf("after tag_check: %d allocated\n", nr_allocated); 302 printf("after tag_check: %d allocated\n", nr_allocated);
241 gang_check(); 303 gang_check();
@@ -244,9 +306,9 @@ static void single_thread_tests(void)
244 printf("after add_and_check: %d allocated\n", nr_allocated); 306 printf("after add_and_check: %d allocated\n", nr_allocated);
245 dynamic_height_check(); 307 dynamic_height_check();
246 printf("after dynamic_height_check: %d allocated\n", nr_allocated); 308 printf("after dynamic_height_check: %d allocated\n", nr_allocated);
247 big_gang_check(); 309 big_gang_check(long_run);
248 printf("after big_gang_check: %d allocated\n", nr_allocated); 310 printf("after big_gang_check: %d allocated\n", nr_allocated);
249 for (i = 0; i < 2000; i++) { 311 for (i = 0; i < (long_run ? 2000 : 3); i++) {
250 copy_tag_check(); 312 copy_tag_check();
251 printf("%d ", i); 313 printf("%d ", i);
252 fflush(stdout); 314 fflush(stdout);
@@ -254,15 +316,23 @@ static void single_thread_tests(void)
254 printf("after copy_tag_check: %d allocated\n", nr_allocated); 316 printf("after copy_tag_check: %d allocated\n", nr_allocated);
255} 317}
256 318
257int main(void) 319int main(int argc, char **argv)
258{ 320{
321 bool long_run = false;
322 int opt;
323
324 while ((opt = getopt(argc, argv, "l")) != -1) {
325 if (opt == 'l')
326 long_run = true;
327 }
328
259 rcu_register_thread(); 329 rcu_register_thread();
260 radix_tree_init(); 330 radix_tree_init();
261 331
262 regression1_test(); 332 regression1_test();
263 regression2_test(); 333 regression2_test();
264 regression3_test(); 334 regression3_test();
265 single_thread_tests(); 335 single_thread_tests(long_run);
266 336
267 sleep(1); 337 sleep(1);
268 printf("after sleep(1): %d allocated\n", nr_allocated); 338 printf("after sleep(1): %d allocated\n", nr_allocated);
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c
new file mode 100644
index 000000000000..39d9b9568fe2
--- /dev/null
+++ b/tools/testing/radix-tree/multiorder.c
@@ -0,0 +1,337 @@
1/*
2 * multiorder.c: Multi-order radix tree entry testing
3 * Copyright (c) 2016 Intel Corporation
4 * Author: Ross Zwisler <ross.zwisler@linux.intel.com>
5 * Author: Matthew Wilcox <matthew.r.wilcox@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 */
16#include <linux/radix-tree.h>
17#include <linux/slab.h>
18#include <linux/errno.h>
19
20#include "test.h"
21
22#define for_each_index(i, base, order) \
23 for (i = base; i < base + (1 << order); i++)
24
25static void __multiorder_tag_test(int index, int order)
26{
27 RADIX_TREE(tree, GFP_KERNEL);
28 int base, err, i;
29 unsigned long first = 0;
30
31 /* our canonical entry */
32 base = index & ~((1 << order) - 1);
33
34 printf("Multiorder tag test with index %d, canonical entry %d\n",
35 index, base);
36
37 err = item_insert_order(&tree, index, order);
38 assert(!err);
39
40 /*
41 * Verify we get collisions for covered indices. We try and fail to
42 * insert an exceptional entry so we don't leak memory via
43 * item_insert_order().
44 */
45 for_each_index(i, base, order) {
46 err = __radix_tree_insert(&tree, i, order,
47 (void *)(0xA0 | RADIX_TREE_EXCEPTIONAL_ENTRY));
48 assert(err == -EEXIST);
49 }
50
51 for_each_index(i, base, order) {
52 assert(!radix_tree_tag_get(&tree, i, 0));
53 assert(!radix_tree_tag_get(&tree, i, 1));
54 }
55
56 assert(radix_tree_tag_set(&tree, index, 0));
57
58 for_each_index(i, base, order) {
59 assert(radix_tree_tag_get(&tree, i, 0));
60 assert(!radix_tree_tag_get(&tree, i, 1));
61 }
62
63 assert(radix_tree_range_tag_if_tagged(&tree, &first, ~0UL, 10, 0, 1) == 1);
64 assert(radix_tree_tag_clear(&tree, index, 0));
65
66 for_each_index(i, base, order) {
67 assert(!radix_tree_tag_get(&tree, i, 0));
68 assert(radix_tree_tag_get(&tree, i, 1));
69 }
70
71 assert(radix_tree_tag_clear(&tree, index, 1));
72
73 assert(!radix_tree_tagged(&tree, 0));
74 assert(!radix_tree_tagged(&tree, 1));
75
76 item_kill_tree(&tree);
77}
78
79static void multiorder_tag_tests(void)
80{
81 /* test multi-order entry for indices 0-7 with no sibling pointers */
82 __multiorder_tag_test(0, 3);
83 __multiorder_tag_test(5, 3);
84
85 /* test multi-order entry for indices 8-15 with no sibling pointers */
86 __multiorder_tag_test(8, 3);
87 __multiorder_tag_test(15, 3);
88
89 /*
90 * Our order 5 entry covers indices 0-31 in a tree with height=2.
91 * This is broken up as follows:
92 * 0-7: canonical entry
93 * 8-15: sibling 1
94 * 16-23: sibling 2
95 * 24-31: sibling 3
96 */
97 __multiorder_tag_test(0, 5);
98 __multiorder_tag_test(29, 5);
99
100 /* same test, but with indices 32-63 */
101 __multiorder_tag_test(32, 5);
102 __multiorder_tag_test(44, 5);
103
104 /*
105 * Our order 8 entry covers indices 0-255 in a tree with height=3.
106 * This is broken up as follows:
107 * 0-63: canonical entry
108 * 64-127: sibling 1
109 * 128-191: sibling 2
110 * 192-255: sibling 3
111 */
112 __multiorder_tag_test(0, 8);
113 __multiorder_tag_test(190, 8);
114
115 /* same test, but with indices 256-511 */
116 __multiorder_tag_test(256, 8);
117 __multiorder_tag_test(300, 8);
118
119 __multiorder_tag_test(0x12345678UL, 8);
120}
121
122static void multiorder_check(unsigned long index, int order)
123{
124 unsigned long i;
125 unsigned long min = index & ~((1UL << order) - 1);
126 unsigned long max = min + (1UL << order);
127 RADIX_TREE(tree, GFP_KERNEL);
128
129 printf("Multiorder index %ld, order %d\n", index, order);
130
131 assert(item_insert_order(&tree, index, order) == 0);
132
133 for (i = min; i < max; i++) {
134 struct item *item = item_lookup(&tree, i);
135 assert(item != 0);
136 assert(item->index == index);
137 }
138 for (i = 0; i < min; i++)
139 item_check_absent(&tree, i);
140 for (i = max; i < 2*max; i++)
141 item_check_absent(&tree, i);
142 for (i = min; i < max; i++) {
143 static void *entry = (void *)
144 (0xA0 | RADIX_TREE_EXCEPTIONAL_ENTRY);
145 assert(radix_tree_insert(&tree, i, entry) == -EEXIST);
146 }
147
148 assert(item_delete(&tree, index) != 0);
149
150 for (i = 0; i < 2*max; i++)
151 item_check_absent(&tree, i);
152}
153
154static void multiorder_shrink(unsigned long index, int order)
155{
156 unsigned long i;
157 unsigned long max = 1 << order;
158 RADIX_TREE(tree, GFP_KERNEL);
159 struct radix_tree_node *node;
160
161 printf("Multiorder shrink index %ld, order %d\n", index, order);
162
163 assert(item_insert_order(&tree, 0, order) == 0);
164
165 node = tree.rnode;
166
167 assert(item_insert(&tree, index) == 0);
168 assert(node != tree.rnode);
169
170 assert(item_delete(&tree, index) != 0);
171 assert(node == tree.rnode);
172
173 for (i = 0; i < max; i++) {
174 struct item *item = item_lookup(&tree, i);
175 assert(item != 0);
176 assert(item->index == 0);
177 }
178 for (i = max; i < 2*max; i++)
179 item_check_absent(&tree, i);
180
181 if (!item_delete(&tree, 0)) {
182 printf("failed to delete index %ld (order %d)\n", index, order); abort();
183 }
184
185 for (i = 0; i < 2*max; i++)
186 item_check_absent(&tree, i);
187}
188
189static void multiorder_insert_bug(void)
190{
191 RADIX_TREE(tree, GFP_KERNEL);
192
193 item_insert(&tree, 0);
194 radix_tree_tag_set(&tree, 0, 0);
195 item_insert_order(&tree, 3 << 6, 6);
196
197 item_kill_tree(&tree);
198}
199
200void multiorder_iteration(void)
201{
202 RADIX_TREE(tree, GFP_KERNEL);
203 struct radix_tree_iter iter;
204 void **slot;
205 int i, j, err;
206
207 printf("Multiorder iteration test\n");
208
209#define NUM_ENTRIES 11
210 int index[NUM_ENTRIES] = {0, 2, 4, 8, 16, 32, 34, 36, 64, 72, 128};
211 int order[NUM_ENTRIES] = {1, 1, 2, 3, 4, 1, 0, 1, 3, 0, 7};
212
213 for (i = 0; i < NUM_ENTRIES; i++) {
214 err = item_insert_order(&tree, index[i], order[i]);
215 assert(!err);
216 }
217
218 for (j = 0; j < 256; j++) {
219 for (i = 0; i < NUM_ENTRIES; i++)
220 if (j <= (index[i] | ((1 << order[i]) - 1)))
221 break;
222
223 radix_tree_for_each_slot(slot, &tree, &iter, j) {
224 int height = order[i] / RADIX_TREE_MAP_SHIFT;
225 int shift = height * RADIX_TREE_MAP_SHIFT;
226 int mask = (1 << order[i]) - 1;
227
228 assert(iter.index >= (index[i] &~ mask));
229 assert(iter.index <= (index[i] | mask));
230 assert(iter.shift == shift);
231 i++;
232 }
233 }
234
235 item_kill_tree(&tree);
236}
237
238void multiorder_tagged_iteration(void)
239{
240 RADIX_TREE(tree, GFP_KERNEL);
241 struct radix_tree_iter iter;
242 void **slot;
243 unsigned long first = 0;
244 int i, j;
245
246 printf("Multiorder tagged iteration test\n");
247
248#define MT_NUM_ENTRIES 9
249 int index[MT_NUM_ENTRIES] = {0, 2, 4, 16, 32, 40, 64, 72, 128};
250 int order[MT_NUM_ENTRIES] = {1, 0, 2, 4, 3, 1, 3, 0, 7};
251
252#define TAG_ENTRIES 7
253 int tag_index[TAG_ENTRIES] = {0, 4, 16, 40, 64, 72, 128};
254
255 for (i = 0; i < MT_NUM_ENTRIES; i++)
256 assert(!item_insert_order(&tree, index[i], order[i]));
257
258 assert(!radix_tree_tagged(&tree, 1));
259
260 for (i = 0; i < TAG_ENTRIES; i++)
261 assert(radix_tree_tag_set(&tree, tag_index[i], 1));
262
263 for (j = 0; j < 256; j++) {
264 int mask, k;
265
266 for (i = 0; i < TAG_ENTRIES; i++) {
267 for (k = i; index[k] < tag_index[i]; k++)
268 ;
269 if (j <= (index[k] | ((1 << order[k]) - 1)))
270 break;
271 }
272
273 radix_tree_for_each_tagged(slot, &tree, &iter, j, 1) {
274 for (k = i; index[k] < tag_index[i]; k++)
275 ;
276 mask = (1 << order[k]) - 1;
277
278 assert(iter.index >= (tag_index[i] &~ mask));
279 assert(iter.index <= (tag_index[i] | mask));
280 i++;
281 }
282 }
283
284 radix_tree_range_tag_if_tagged(&tree, &first, ~0UL,
285 MT_NUM_ENTRIES, 1, 2);
286
287 for (j = 0; j < 256; j++) {
288 int mask, k;
289
290 for (i = 0; i < TAG_ENTRIES; i++) {
291 for (k = i; index[k] < tag_index[i]; k++)
292 ;
293 if (j <= (index[k] | ((1 << order[k]) - 1)))
294 break;
295 }
296
297 radix_tree_for_each_tagged(slot, &tree, &iter, j, 2) {
298 for (k = i; index[k] < tag_index[i]; k++)
299 ;
300 mask = (1 << order[k]) - 1;
301
302 assert(iter.index >= (tag_index[i] &~ mask));
303 assert(iter.index <= (tag_index[i] | mask));
304 i++;
305 }
306 }
307
308 first = 1;
309 radix_tree_range_tag_if_tagged(&tree, &first, ~0UL,
310 MT_NUM_ENTRIES, 1, 0);
311 i = 0;
312 radix_tree_for_each_tagged(slot, &tree, &iter, 0, 0) {
313 assert(iter.index == tag_index[i]);
314 i++;
315 }
316
317 item_kill_tree(&tree);
318}
319
320void multiorder_checks(void)
321{
322 int i;
323
324 for (i = 0; i < 20; i++) {
325 multiorder_check(200, i);
326 multiorder_check(0, i);
327 multiorder_check((1UL << i) + 1, i);
328 }
329
330 for (i = 0; i < 15; i++)
331 multiorder_shrink((1UL << (i + RADIX_TREE_MAP_SHIFT)), i);
332
333 multiorder_insert_bug();
334 multiorder_tag_tests();
335 multiorder_iteration();
336 multiorder_tagged_iteration();
337}
diff --git a/tools/testing/radix-tree/regression2.c b/tools/testing/radix-tree/regression2.c
index 5d2fa28cdca3..63bf347aaf33 100644
--- a/tools/testing/radix-tree/regression2.c
+++ b/tools/testing/radix-tree/regression2.c
@@ -51,13 +51,6 @@
51 51
52#include "regression.h" 52#include "regression.h"
53 53
54#ifdef __KERNEL__
55#define RADIX_TREE_MAP_SHIFT (CONFIG_BASE_SMALL ? 4 : 6)
56#else
57#define RADIX_TREE_MAP_SHIFT 3 /* For more stressful testing */
58#endif
59
60#define RADIX_TREE_MAP_SIZE (1UL << RADIX_TREE_MAP_SHIFT)
61#define PAGECACHE_TAG_DIRTY 0 54#define PAGECACHE_TAG_DIRTY 0
62#define PAGECACHE_TAG_WRITEBACK 1 55#define PAGECACHE_TAG_WRITEBACK 1
63#define PAGECACHE_TAG_TOWRITE 2 56#define PAGECACHE_TAG_TOWRITE 2
diff --git a/tools/testing/radix-tree/tag_check.c b/tools/testing/radix-tree/tag_check.c
index 83136be552a0..b7447ceb75e9 100644
--- a/tools/testing/radix-tree/tag_check.c
+++ b/tools/testing/radix-tree/tag_check.c
@@ -12,6 +12,7 @@
12static void 12static void
13__simple_checks(struct radix_tree_root *tree, unsigned long index, int tag) 13__simple_checks(struct radix_tree_root *tree, unsigned long index, int tag)
14{ 14{
15 unsigned long first = 0;
15 int ret; 16 int ret;
16 17
17 item_check_absent(tree, index); 18 item_check_absent(tree, index);
@@ -22,6 +23,10 @@ __simple_checks(struct radix_tree_root *tree, unsigned long index, int tag)
22 item_tag_set(tree, index, tag); 23 item_tag_set(tree, index, tag);
23 ret = item_tag_get(tree, index, tag); 24 ret = item_tag_get(tree, index, tag);
24 assert(ret != 0); 25 assert(ret != 0);
26 ret = radix_tree_range_tag_if_tagged(tree, &first, ~0UL, 10, tag, !tag);
27 assert(ret == 1);
28 ret = item_tag_get(tree, index, !tag);
29 assert(ret != 0);
25 ret = item_delete(tree, index); 30 ret = item_delete(tree, index);
26 assert(ret != 0); 31 assert(ret != 0);
27 item_insert(tree, index); 32 item_insert(tree, index);
@@ -304,6 +309,7 @@ static void single_check(void)
304 struct item *items[BATCH]; 309 struct item *items[BATCH];
305 RADIX_TREE(tree, GFP_KERNEL); 310 RADIX_TREE(tree, GFP_KERNEL);
306 int ret; 311 int ret;
312 unsigned long first = 0;
307 313
308 item_insert(&tree, 0); 314 item_insert(&tree, 0);
309 item_tag_set(&tree, 0, 0); 315 item_tag_set(&tree, 0, 0);
@@ -313,6 +319,10 @@ static void single_check(void)
313 assert(ret == 0); 319 assert(ret == 0);
314 verify_tag_consistency(&tree, 0); 320 verify_tag_consistency(&tree, 0);
315 verify_tag_consistency(&tree, 1); 321 verify_tag_consistency(&tree, 1);
322 ret = radix_tree_range_tag_if_tagged(&tree, &first, 10, 10, 0, 1);
323 assert(ret == 1);
324 ret = radix_tree_gang_lookup_tag(&tree, (void **)items, 0, BATCH, 1);
325 assert(ret == 1);
316 item_kill_tree(&tree); 326 item_kill_tree(&tree);
317} 327}
318 328
diff --git a/tools/testing/radix-tree/test.c b/tools/testing/radix-tree/test.c
index 2bebf34cdc27..a6e8099eaf4f 100644
--- a/tools/testing/radix-tree/test.c
+++ b/tools/testing/radix-tree/test.c
@@ -24,14 +24,21 @@ int item_tag_get(struct radix_tree_root *root, unsigned long index, int tag)
24 return radix_tree_tag_get(root, index, tag); 24 return radix_tree_tag_get(root, index, tag);
25} 25}
26 26
27int __item_insert(struct radix_tree_root *root, struct item *item) 27int __item_insert(struct radix_tree_root *root, struct item *item,
28 unsigned order)
28{ 29{
29 return radix_tree_insert(root, item->index, item); 30 return __radix_tree_insert(root, item->index, order, item);
30} 31}
31 32
32int item_insert(struct radix_tree_root *root, unsigned long index) 33int item_insert(struct radix_tree_root *root, unsigned long index)
33{ 34{
34 return __item_insert(root, item_create(index)); 35 return __item_insert(root, item_create(index), 0);
36}
37
38int item_insert_order(struct radix_tree_root *root, unsigned long index,
39 unsigned order)
40{
41 return __item_insert(root, item_create(index), order);
35} 42}
36 43
37int item_delete(struct radix_tree_root *root, unsigned long index) 44int item_delete(struct radix_tree_root *root, unsigned long index)
@@ -136,13 +143,13 @@ void item_full_scan(struct radix_tree_root *root, unsigned long start,
136} 143}
137 144
138static int verify_node(struct radix_tree_node *slot, unsigned int tag, 145static int verify_node(struct radix_tree_node *slot, unsigned int tag,
139 unsigned int height, int tagged) 146 int tagged)
140{ 147{
141 int anyset = 0; 148 int anyset = 0;
142 int i; 149 int i;
143 int j; 150 int j;
144 151
145 slot = indirect_to_ptr(slot); 152 slot = entry_to_node(slot);
146 153
147 /* Verify consistency at this level */ 154 /* Verify consistency at this level */
148 for (i = 0; i < RADIX_TREE_TAG_LONGS; i++) { 155 for (i = 0; i < RADIX_TREE_TAG_LONGS; i++) {
@@ -152,7 +159,8 @@ static int verify_node(struct radix_tree_node *slot, unsigned int tag,
152 } 159 }
153 } 160 }
154 if (tagged != anyset) { 161 if (tagged != anyset) {
155 printf("tag: %u, height %u, tagged: %d, anyset: %d\n", tag, height, tagged, anyset); 162 printf("tag: %u, shift %u, tagged: %d, anyset: %d\n",
163 tag, slot->shift, tagged, anyset);
156 for (j = 0; j < RADIX_TREE_MAX_TAGS; j++) { 164 for (j = 0; j < RADIX_TREE_MAX_TAGS; j++) {
157 printf("tag %d: ", j); 165 printf("tag %d: ", j);
158 for (i = 0; i < RADIX_TREE_TAG_LONGS; i++) 166 for (i = 0; i < RADIX_TREE_TAG_LONGS; i++)
@@ -164,10 +172,10 @@ static int verify_node(struct radix_tree_node *slot, unsigned int tag,
164 assert(tagged == anyset); 172 assert(tagged == anyset);
165 173
166 /* Go for next level */ 174 /* Go for next level */
167 if (height > 1) { 175 if (slot->shift > 0) {
168 for (i = 0; i < RADIX_TREE_MAP_SIZE; i++) 176 for (i = 0; i < RADIX_TREE_MAP_SIZE; i++)
169 if (slot->slots[i]) 177 if (slot->slots[i])
170 if (verify_node(slot->slots[i], tag, height - 1, 178 if (verify_node(slot->slots[i], tag,
171 !!test_bit(i, slot->tags[tag]))) { 179 !!test_bit(i, slot->tags[tag]))) {
172 printf("Failure at off %d\n", i); 180 printf("Failure at off %d\n", i);
173 for (j = 0; j < RADIX_TREE_MAX_TAGS; j++) { 181 for (j = 0; j < RADIX_TREE_MAX_TAGS; j++) {
@@ -184,9 +192,10 @@ static int verify_node(struct radix_tree_node *slot, unsigned int tag,
184 192
185void verify_tag_consistency(struct radix_tree_root *root, unsigned int tag) 193void verify_tag_consistency(struct radix_tree_root *root, unsigned int tag)
186{ 194{
187 if (!root->height) 195 struct radix_tree_node *node = root->rnode;
196 if (!radix_tree_is_internal_node(node))
188 return; 197 return;
189 verify_node(root->rnode, tag, root->height, !!root_tag_get(root, tag)); 198 verify_node(node, tag, !!root_tag_get(root, tag));
190} 199}
191 200
192void item_kill_tree(struct radix_tree_root *root) 201void item_kill_tree(struct radix_tree_root *root)
@@ -211,9 +220,19 @@ void item_kill_tree(struct radix_tree_root *root)
211 220
212void tree_verify_min_height(struct radix_tree_root *root, int maxindex) 221void tree_verify_min_height(struct radix_tree_root *root, int maxindex)
213{ 222{
214 assert(radix_tree_maxindex(root->height) >= maxindex); 223 unsigned shift;
215 if (root->height > 1) 224 struct radix_tree_node *node = root->rnode;
216 assert(radix_tree_maxindex(root->height-1) < maxindex); 225 if (!radix_tree_is_internal_node(node)) {
217 else if (root->height == 1) 226 assert(maxindex == 0);
218 assert(radix_tree_maxindex(root->height-1) <= maxindex); 227 return;
228 }
229
230 node = entry_to_node(node);
231 assert(maxindex <= node_maxindex(node));
232
233 shift = node->shift;
234 if (shift > 0)
235 assert(maxindex > shift_maxindex(shift - RADIX_TREE_MAP_SHIFT));
236 else
237 assert(maxindex > 0);
219} 238}
diff --git a/tools/testing/radix-tree/test.h b/tools/testing/radix-tree/test.h
index 4e1d95faaa94..e85131369723 100644
--- a/tools/testing/radix-tree/test.h
+++ b/tools/testing/radix-tree/test.h
@@ -8,8 +8,11 @@ struct item {
8}; 8};
9 9
10struct item *item_create(unsigned long index); 10struct item *item_create(unsigned long index);
11int __item_insert(struct radix_tree_root *root, struct item *item); 11int __item_insert(struct radix_tree_root *root, struct item *item,
12 unsigned order);
12int item_insert(struct radix_tree_root *root, unsigned long index); 13int item_insert(struct radix_tree_root *root, unsigned long index);
14int item_insert_order(struct radix_tree_root *root, unsigned long index,
15 unsigned order);
13int item_delete(struct radix_tree_root *root, unsigned long index); 16int item_delete(struct radix_tree_root *root, unsigned long index);
14struct item *item_lookup(struct radix_tree_root *root, unsigned long index); 17struct item *item_lookup(struct radix_tree_root *root, unsigned long index);
15 18
@@ -23,6 +26,7 @@ void item_full_scan(struct radix_tree_root *root, unsigned long start,
23void item_kill_tree(struct radix_tree_root *root); 26void item_kill_tree(struct radix_tree_root *root);
24 27
25void tag_check(void); 28void tag_check(void);
29void multiorder_checks(void);
26 30
27struct item * 31struct item *
28item_tag_set(struct radix_tree_root *root, unsigned long index, int tag); 32item_tag_set(struct radix_tree_root *root, unsigned long index, int tag);
@@ -35,6 +39,7 @@ void verify_tag_consistency(struct radix_tree_root *root, unsigned int tag);
35extern int nr_allocated; 39extern int nr_allocated;
36 40
37/* Normally private parts of lib/radix-tree.c */ 41/* Normally private parts of lib/radix-tree.c */
38void *indirect_to_ptr(void *ptr); 42void radix_tree_dump(struct radix_tree_root *root);
39int root_tag_get(struct radix_tree_root *root, unsigned int tag); 43int root_tag_get(struct radix_tree_root *root, unsigned int tag);
40unsigned long radix_tree_maxindex(unsigned int height); 44unsigned long node_maxindex(struct radix_tree_node *);
45unsigned long shift_maxindex(unsigned int shift);
diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
index da48812ab95e..4c6a0bf8ba79 100755
--- a/tools/testing/selftests/ftrace/ftracetest
+++ b/tools/testing/selftests/ftrace/ftracetest
@@ -88,7 +88,12 @@ parse_opts() { # opts
88 88
89# Parameters 89# Parameters
90DEBUGFS_DIR=`grep debugfs /proc/mounts | cut -f2 -d' ' | head -1` 90DEBUGFS_DIR=`grep debugfs /proc/mounts | cut -f2 -d' ' | head -1`
91TRACING_DIR=$DEBUGFS_DIR/tracing 91if [ -z "$DEBUGFS_DIR" ]; then
92 TRACING_DIR=`grep tracefs /proc/mounts | cut -f2 -d' ' | head -1`
93else
94 TRACING_DIR=$DEBUGFS_DIR/tracing
95fi
96
92TOP_DIR=`absdir $0` 97TOP_DIR=`absdir $0`
93TEST_DIR=$TOP_DIR/test.d 98TEST_DIR=$TOP_DIR/test.d
94TEST_CASES=`find_testcases $TEST_DIR` 99TEST_CASES=`find_testcases $TEST_DIR`
@@ -102,7 +107,7 @@ parse_opts $*
102[ $DEBUG -ne 0 ] && set -x 107[ $DEBUG -ne 0 ] && set -x
103 108
104# Verify parameters 109# Verify parameters
105if [ -z "$DEBUGFS_DIR" -o ! -d "$TRACING_DIR" ]; then 110if [ -z "$TRACING_DIR" -o ! -d "$TRACING_DIR" ]; then
106 errexit "No ftrace directory found" 111 errexit "No ftrace directory found"
107fi 112fi
108 113
diff --git a/tools/testing/selftests/ftrace/test.d/event/event-pid.tc b/tools/testing/selftests/ftrace/test.d/event/event-pid.tc
new file mode 100644
index 000000000000..d4ab27b522f8
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/event/event-pid.tc
@@ -0,0 +1,72 @@
1#!/bin/sh
2# description: event tracing - restricts events based on pid
3
4do_reset() {
5 echo > set_event
6 echo > set_event_pid
7 echo 0 > options/event-fork
8 clear_trace
9}
10
11fail() { #msg
12 do_reset
13 echo $1
14 exit $FAIL
15}
16
17yield() {
18 ping localhost -c 1 || sleep .001 || usleep 1 || sleep 1
19}
20
21if [ ! -f set_event -o ! -d events/sched ]; then
22 echo "event tracing is not supported"
23 exit_unsupported
24fi
25
26if [ ! -f set_event_pid ]; then
27 echo "event pid filtering is not supported"
28 exit_unsupported
29fi
30
31reset_tracer
32do_reset
33
34echo 1 > events/sched/sched_switch/enable
35
36yield
37
38count=`cat trace | grep sched_switch | wc -l`
39if [ $count -eq 0 ]; then
40 fail "sched_switch events are not recorded"
41fi
42
43do_reset
44
45read mypid rest < /proc/self/stat
46
47echo $mypid > set_event_pid
48echo 'sched:sched_switch' > set_event
49
50yield
51
52count=`cat trace | grep sched_switch | grep -v "pid=$mypid" | wc -l`
53if [ $count -ne 0 ]; then
54 fail "sched_switch events from other task are recorded"
55fi
56
57do_reset
58
59echo $mypid > set_event_pid
60echo 1 > options/event-fork
61echo 1 > events/sched/sched_switch/enable
62
63yield
64
65count=`cat trace | grep sched_switch | grep -v "pid=$mypid" | wc -l`
66if [ $count -eq 0 ]; then
67 fail "sched_switch events from other task are not recorded"
68fi
69
70do_reset
71
72exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/functions b/tools/testing/selftests/ftrace/test.d/functions
index 5d8cd06d920f..c37262f6c269 100644
--- a/tools/testing/selftests/ftrace/test.d/functions
+++ b/tools/testing/selftests/ftrace/test.d/functions
@@ -14,3 +14,12 @@ enable_tracing() { # start trace recording
14reset_tracer() { # reset the current tracer 14reset_tracer() { # reset the current tracer
15 echo nop > current_tracer 15 echo nop > current_tracer
16} 16}
17
18reset_trigger() { # reset all current setting triggers
19 grep -v ^# events/*/*/trigger |
20 while read line; do
21 cmd=`echo $line | cut -f2- -d: | cut -f1 -d" "`
22 echo "!$cmd" > `echo $line | cut -f1 -d:`
23 done
24}
25
diff --git a/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc b/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc
new file mode 100644
index 000000000000..4c5a061a5b4e
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc
@@ -0,0 +1,138 @@
1#!/bin/sh
2# description: Test creation and deletion of trace instances while setting an event
3
4if [ ! -d instances ] ; then
5 echo "no instance directory with this kernel"
6 exit_unsupported;
7fi
8
9fail() { # mesg
10 rmdir foo 2>/dev/null
11 echo $1
12 set -e
13 exit $FAIL
14}
15
16cd instances
17
18# we don't want to fail on error
19set +e
20
21mkdir x
22rmdir x
23result=$?
24
25if [ $result -ne 0 ]; then
26 echo "instance rmdir not supported"
27 exit_unsupported
28fi
29
30instance_slam() {
31 while :; do
32 mkdir foo 2> /dev/null
33 rmdir foo 2> /dev/null
34 done
35}
36
37instance_read() {
38 while :; do
39 cat foo/trace 1> /dev/null 2>&1
40 done
41}
42
43instance_set() {
44 while :; do
45 echo 1 > foo/events/sched/sched_switch
46 done 2> /dev/null
47}
48
49instance_slam &
50p1=$!
51echo $p1
52
53instance_set &
54p2=$!
55echo $p2
56
57instance_read &
58p3=$!
59echo $p3
60
61sleep 1
62
63kill -1 $p3
64kill -1 $p2
65kill -1 $p1
66
67echo "Wait for processes to finish"
68wait $p1 $p2 $p3
69echo "all processes finished, wait for cleanup"
70sleep 1
71
72mkdir foo
73ls foo > /dev/null
74rmdir foo
75if [ -d foo ]; then
76 fail "foo still exists"
77fi
78exit 0
79
80
81
82
83instance_slam() {
84 while :; do
85 mkdir x
86 mkdir y
87 mkdir z
88 rmdir x
89 rmdir y
90 rmdir z
91 done 2>/dev/null
92}
93
94instance_slam &
95p1=$!
96echo $p1
97
98instance_slam &
99p2=$!
100echo $p2
101
102instance_slam &
103p3=$!
104echo $p3
105
106instance_slam &
107p4=$!
108echo $p4
109
110instance_slam &
111p5=$!
112echo $p5
113
114ls -lR >/dev/null
115sleep 1
116
117kill -1 $p1
118kill -1 $p2
119kill -1 $p3
120kill -1 $p4
121kill -1 $p5
122
123echo "Wait for processes to finish"
124wait $p1 $p2 $p3 $p4 $p5
125echo "all processes finished, wait for cleanup"
126
127mkdir x y z
128ls x y z
129rmdir x y z
130for d in x y z; do
131 if [ -d $d ]; then
132 fail "instance $d still exists"
133 fi
134done
135
136set -e
137
138exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc
new file mode 100644
index 000000000000..1a9445021bf1
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc
@@ -0,0 +1,64 @@
1#!/bin/sh
2# description: event trigger - test event enable/disable trigger
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep enable_event events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "event enable/disable trigger is not supported"
32 exit_unsupported
33fi
34
35echo "Test enable_event trigger"
36echo 0 > events/sched/sched_switch/enable
37echo 'enable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger
38( echo "forked")
39if [ `cat events/sched/sched_switch/enable` != '1*' ]; then
40 fail "enable_event trigger on sched_process_fork did not work"
41fi
42
43reset_trigger
44
45echo "Test disable_event trigger"
46echo 1 > events/sched/sched_switch/enable
47echo 'disable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger
48( echo "forked")
49if [ `cat events/sched/sched_switch/enable` != '0*' ]; then
50 fail "disable_event trigger on sched_process_fork did not work"
51fi
52
53reset_trigger
54
55echo "Test semantic error for event enable/disable trigger"
56! echo 'enable_event:nogroup:noevent' > events/sched/sched_process_fork/trigger
57! echo 'disable_event+1' > events/sched/sched_process_fork/trigger
58echo 'enable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger
59! echo 'enable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger
60! echo 'disable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger
61
62do_reset
63
64exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc
new file mode 100644
index 000000000000..514e466e198b
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc
@@ -0,0 +1,59 @@
1#!/bin/sh
2# description: event trigger - test trigger filter
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29echo "Test trigger filter"
30echo 1 > tracing_on
31echo 'traceoff if child_pid == 0' > events/sched/sched_process_fork/trigger
32( echo "forked")
33if [ `cat tracing_on` -ne 1 ]; then
34 fail "traceoff trigger on sched_process_fork did not work"
35fi
36
37reset_trigger
38
39echo "Test semantic error for trigger filter"
40! echo 'traceoff if a' > events/sched/sched_process_fork/trigger
41! echo 'traceoff if common_pid=0' > events/sched/sched_process_fork/trigger
42! echo 'traceoff if common_pid==b' > events/sched/sched_process_fork/trigger
43echo 'traceoff if common_pid == 0' > events/sched/sched_process_fork/trigger
44echo '!traceoff' > events/sched/sched_process_fork/trigger
45! echo 'traceoff if common_pid == child_pid' > events/sched/sched_process_fork/trigger
46echo 'traceoff if common_pid <= 0' > events/sched/sched_process_fork/trigger
47echo '!traceoff' > events/sched/sched_process_fork/trigger
48echo 'traceoff if common_pid >= 0' > events/sched/sched_process_fork/trigger
49echo '!traceoff' > events/sched/sched_process_fork/trigger
50echo 'traceoff if parent_pid >= 0 && child_pid >= 0' > events/sched/sched_process_fork/trigger
51echo '!traceoff' > events/sched/sched_process_fork/trigger
52echo 'traceoff if parent_pid >= 0 || child_pid >= 0' > events/sched/sched_process_fork/trigger
53echo '!traceoff' > events/sched/sched_process_fork/trigger
54
55
56
57do_reset
58
59exit 0
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
new file mode 100644
index 000000000000..c2b61c4fda11
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc
@@ -0,0 +1,75 @@
1#!/bin/sh
2# description: event trigger - test histogram modifiers
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep hist events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "hist trigger is not supported"
32 exit_unsupported
33fi
34
35echo "Test histogram with execname modifier"
36
37echo 'hist:keys=common_pid.execname' > events/sched/sched_process_fork/trigger
38for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
39COMM=`cat /proc/$$/comm`
40grep "common_pid: $COMM" events/sched/sched_process_fork/hist > /dev/null || \
41 fail "execname modifier on sched_process_fork did not work"
42
43reset_trigger
44
45echo "Test histogram with hex modifier"
46
47echo 'hist:keys=parent_pid.hex' > events/sched/sched_process_fork/trigger
48for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
49# Note that $$ is the parent pid. $PID is current PID.
50HEX=`printf %x $PID`
51grep "parent_pid: $HEX" events/sched/sched_process_fork/hist > /dev/null || \
52 fail "hex modifier on sched_process_fork did not work"
53
54reset_trigger
55
56echo "Test histogram with syscall modifier"
57
58echo 'hist:keys=id.syscall' > events/raw_syscalls/sys_exit/trigger
59for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
60grep "id: sys_" events/raw_syscalls/sys_exit/hist > /dev/null || \
61 fail "syscall modifier on raw_syscalls/sys_exit did not work"
62
63
64reset_trigger
65
66echo "Test histgram with log2 modifier"
67
68echo 'hist:keys=bytes_req.log2' > events/kmem/kmalloc/trigger
69for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
70grep 'bytes_req: ~ 2^[0-9]*' events/kmem/kmalloc/hist > /dev/null || \
71 fail "log2 modifier on kmem/kmalloc did not work"
72
73do_reset
74
75exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc
new file mode 100644
index 000000000000..b2902d42a537
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc
@@ -0,0 +1,83 @@
1#!/bin/sh
2# description: event trigger - test histogram trigger
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep hist events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "hist trigger is not supported"
32 exit_unsupported
33fi
34
35echo "Test histogram basic tigger"
36
37echo 'hist:keys=parent_pid:vals=child_pid' > events/sched/sched_process_fork/trigger
38for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
39grep parent_pid events/sched/sched_process_fork/hist > /dev/null || \
40 fail "hist trigger on sched_process_fork did not work"
41grep child events/sched/sched_process_fork/hist > /dev/null || \
42 fail "hist trigger on sched_process_fork did not work"
43
44reset_trigger
45
46echo "Test histogram with compound keys"
47
48echo 'hist:keys=parent_pid,child_pid' > events/sched/sched_process_fork/trigger
49for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
50grep '^{ parent_pid:.*, child_pid:.*}' events/sched/sched_process_fork/hist > /dev/null || \
51 fail "compound keys on sched_process_fork did not work"
52
53reset_trigger
54
55echo "Test histogram with string key"
56
57echo 'hist:keys=parent_comm' > events/sched/sched_process_fork/trigger
58for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
59COMM=`cat /proc/$$/comm`
60grep "parent_comm: $COMM" events/sched/sched_process_fork/hist > /dev/null || \
61 fail "string key on sched_process_fork did not work"
62
63reset_trigger
64
65echo "Test histogram with sort key"
66
67echo 'hist:keys=parent_pid,child_pid:sort=child_pid.ascending' > events/sched/sched_process_fork/trigger
68for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
69
70check_inc() {
71 while [ $# -gt 1 ]; do
72 [ $1 -gt $2 ] && return 1
73 shift 1
74 done
75 return 0
76}
77check_inc `grep -o "child_pid:[[:space:]]*[[:digit:]]*" \
78 events/sched/sched_process_fork/hist | cut -d: -f2 ` ||
79 fail "sort param on sched_process_fork did not work"
80
81do_reset
82
83exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc
new file mode 100644
index 000000000000..03c4a46561fc
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc
@@ -0,0 +1,73 @@
1#!/bin/sh
2# description: event trigger - test multiple histogram triggers
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep hist events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "hist trigger is not supported"
32 exit_unsupported
33fi
34
35reset_trigger
36
37echo "Test histogram multiple tiggers"
38
39echo 'hist:keys=parent_pid:vals=child_pid' > events/sched/sched_process_fork/trigger
40echo 'hist:keys=parent_comm:vals=child_pid' >> events/sched/sched_process_fork/trigger
41for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
42grep parent_pid events/sched/sched_process_fork/hist > /dev/null || \
43 fail "hist trigger on sched_process_fork did not work"
44grep child events/sched/sched_process_fork/hist > /dev/null || \
45 fail "hist trigger on sched_process_fork did not work"
46COMM=`cat /proc/$$/comm`
47grep "parent_comm: $COMM" events/sched/sched_process_fork/hist > /dev/null || \
48 fail "string key on sched_process_fork did not work"
49
50reset_trigger
51
52echo "Test histogram with its name"
53
54echo 'hist:name=test_hist:keys=common_pid' > events/sched/sched_process_fork/trigger
55for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
56grep test_hist events/sched/sched_process_fork/hist > /dev/null || \
57 fail "named event on sched_process_fork did not work"
58
59echo "Test same named histogram on different events"
60
61echo 'hist:name=test_hist:keys=common_pid' > events/sched/sched_process_exit/trigger
62for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
63grep test_hist events/sched/sched_process_exit/hist > /dev/null || \
64 fail "named event on sched_process_fork did not work"
65
66diffs=`diff events/sched/sched_process_exit/hist events/sched/sched_process_fork/hist | wc -l`
67test $diffs -eq 0 || fail "Same name histograms are not same"
68
69reset_trigger
70
71do_reset
72
73exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc
new file mode 100644
index 000000000000..f84b80d551a2
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc
@@ -0,0 +1,56 @@
1#!/bin/sh
2# description: event trigger - test snapshot-trigger
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep snapshot events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "snapshot trigger is not supported"
32 exit_unsupported
33fi
34
35echo "Test snapshot tigger"
36echo 0 > snapshot
37echo 1 > events/sched/sched_process_fork/enable
38( echo "forked")
39echo 'snapshot:1' > events/sched/sched_process_fork/trigger
40( echo "forked")
41grep sched_process_fork snapshot > /dev/null || \
42 fail "snapshot trigger on sched_process_fork did not work"
43
44reset_trigger
45echo 0 > snapshot
46echo 0 > events/sched/sched_process_fork/enable
47
48echo "Test snapshot semantic errors"
49
50! echo "snapshot+1" > events/sched/sched_process_fork/trigger
51echo "snapshot" > events/sched/sched_process_fork/trigger
52! echo "snapshot" > events/sched/sched_process_fork/trigger
53
54do_reset
55
56exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc
new file mode 100644
index 000000000000..9fa23b085def
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc
@@ -0,0 +1,53 @@
1#!/bin/sh
2# description: event trigger - test stacktrace-trigger
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep stacktrace events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "stacktrace trigger is not supported"
32 exit_unsupported
33fi
34
35echo "Test stacktrace tigger"
36echo 0 > trace
37echo 0 > options/stacktrace
38echo 'stacktrace' > events/sched/sched_process_fork/trigger
39( echo "forked")
40grep "<stack trace>" trace > /dev/null || \
41 fail "stacktrace trigger on sched_process_fork did not work"
42
43reset_trigger
44
45echo "Test stacktrace semantic errors"
46
47! echo "stacktrace:foo" > events/sched/sched_process_fork/trigger
48echo "stacktrace" > events/sched/sched_process_fork/trigger
49! echo "stacktrace" > events/sched/sched_process_fork/trigger
50
51do_reset
52
53exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc
new file mode 100644
index 000000000000..87648e5f987c
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc
@@ -0,0 +1,58 @@
1#!/bin/sh
2# description: event trigger - test traceon/off trigger
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29echo "Test traceoff trigger"
30echo 1 > tracing_on
31echo 'traceoff' > events/sched/sched_process_fork/trigger
32( echo "forked")
33if [ `cat tracing_on` -ne 0 ]; then
34 fail "traceoff trigger on sched_process_fork did not work"
35fi
36
37reset_trigger
38
39echo "Test traceon trigger"
40echo 0 > tracing_on
41echo 'traceon' > events/sched/sched_process_fork/trigger
42( echo "forked")
43if [ `cat tracing_on` -ne 1 ]; then
44 fail "traceoff trigger on sched_process_fork did not work"
45fi
46
47reset_trigger
48
49echo "Test semantic error for traceoff/on trigger"
50! echo 'traceoff:badparam' > events/sched/sched_process_fork/trigger
51! echo 'traceoff+0' > events/sched/sched_process_fork/trigger
52echo 'traceon' > events/sched/sched_process_fork/trigger
53! echo 'traceon' > events/sched/sched_process_fork/trigger
54! echo 'traceoff' > events/sched/sched_process_fork/trigger
55
56do_reset
57
58exit 0
diff --git a/tools/testing/selftests/intel_pstate/run.sh b/tools/testing/selftests/intel_pstate/run.sh
index bdaf37e92684..7868c106b8b1 100755
--- a/tools/testing/selftests/intel_pstate/run.sh
+++ b/tools/testing/selftests/intel_pstate/run.sh
@@ -32,7 +32,7 @@ EVALUATE_ONLY=0
32max_cpus=$(($(nproc)-1)) 32max_cpus=$(($(nproc)-1))
33 33
34# compile programs 34# compile programs
35gcc -o aperf aperf.c -lm 35gcc aperf.c -Wall -D_GNU_SOURCE -o aperf -lm
36[ $? -ne 0 ] && echo "Problem compiling aperf.c." && exit 1 36[ $? -ne 0 ] && echo "Problem compiling aperf.c." && exit 1
37gcc -o msr msr.c -lm 37gcc -o msr msr.c -lm
38[ $? -ne 0 ] && echo "Problem compiling msr.c." && exit 1 38[ $? -ne 0 ] && echo "Problem compiling msr.c." && exit 1
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
index b08f77cbe31b..4ca83fe80654 100644
--- a/tools/testing/selftests/powerpc/Makefile
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -14,6 +14,7 @@ export CFLAGS
14 14
15SUB_DIRS = benchmarks \ 15SUB_DIRS = benchmarks \
16 copyloops \ 16 copyloops \
17 context_switch \
17 dscr \ 18 dscr \
18 mm \ 19 mm \
19 pmu \ 20 pmu \
diff --git a/tools/testing/selftests/powerpc/context_switch/.gitignore b/tools/testing/selftests/powerpc/context_switch/.gitignore
new file mode 100644
index 000000000000..c1431af7b51c
--- /dev/null
+++ b/tools/testing/selftests/powerpc/context_switch/.gitignore
@@ -0,0 +1 @@
cp_abort
diff --git a/tools/testing/selftests/powerpc/context_switch/Makefile b/tools/testing/selftests/powerpc/context_switch/Makefile
new file mode 100644
index 000000000000..e164d1466466
--- /dev/null
+++ b/tools/testing/selftests/powerpc/context_switch/Makefile
@@ -0,0 +1,10 @@
1TEST_PROGS := cp_abort
2
3all: $(TEST_PROGS)
4
5$(TEST_PROGS): ../harness.c ../utils.c
6
7include ../../lib.mk
8
9clean:
10 rm -f $(TEST_PROGS)
diff --git a/tools/testing/selftests/powerpc/context_switch/cp_abort.c b/tools/testing/selftests/powerpc/context_switch/cp_abort.c
new file mode 100644
index 000000000000..5a5b55afda0e
--- /dev/null
+++ b/tools/testing/selftests/powerpc/context_switch/cp_abort.c
@@ -0,0 +1,110 @@
1/*
2 * Adapted from Anton Blanchard's context switch microbenchmark.
3 *
4 * Copyright 2009, Anton Blanchard, IBM Corporation.
5 * Copyright 2016, Mikey Neuling, Chris Smart, IBM Corporation.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
12 * This program tests the copy paste abort functionality of a P9
13 * (or later) by setting up two processes on the same CPU, one
14 * which executes the copy instruction and the other which
15 * executes paste.
16 *
17 * The paste instruction should never succeed, as the cp_abort
18 * instruction is called by the kernel during a context switch.
19 *
20 */
21
22#define _GNU_SOURCE
23
24#include <stdio.h>
25#include <unistd.h>
26#include <stdlib.h>
27#include "utils.h"
28#include <sched.h>
29
30#define READ_FD 0
31#define WRITE_FD 1
32
33#define NUM_LOOPS 1000
34
35/* This defines the "paste" instruction from Power ISA 3.0 Book II, section 4.4. */
36#define PASTE(RA, RB, L, RC) \
37 .long (0x7c00070c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10) | (RC) << (31-31))
38
39int paste(void *i)
40{
41 int cr;
42
43 asm volatile(str(PASTE(0, %1, 1, 1))";"
44 "mfcr %0;"
45 : "=r" (cr)
46 : "b" (i)
47 : "memory"
48 );
49 return cr;
50}
51
52/* This defines the "copy" instruction from Power ISA 3.0 Book II, section 4.4. */
53#define COPY(RA, RB, L) \
54 .long (0x7c00060c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10))
55
56void copy(void *i)
57{
58 asm volatile(str(COPY(0, %0, 1))";"
59 :
60 : "b" (i)
61 : "memory"
62 );
63}
64
65int test_cp_abort(void)
66{
67 /* 128 bytes for a full cache line */
68 char buf[128] __cacheline_aligned;
69 cpu_set_t cpuset;
70 int fd1[2], fd2[2], pid;
71 char c;
72
73 /* only run this test on a P9 or later */
74 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00));
75
76 /*
77 * Run both processes on the same CPU, so that copy is more likely
78 * to leak into a paste.
79 */
80 CPU_ZERO(&cpuset);
81 CPU_SET(pick_online_cpu(), &cpuset);
82 FAIL_IF(sched_setaffinity(0, sizeof(cpuset), &cpuset));
83
84 FAIL_IF(pipe(fd1) || pipe(fd2));
85
86 pid = fork();
87 FAIL_IF(pid < 0);
88
89 if (!pid) {
90 for (int i = 0; i < NUM_LOOPS; i++) {
91 FAIL_IF((write(fd1[WRITE_FD], &c, 1)) != 1);
92 FAIL_IF((read(fd2[READ_FD], &c, 1)) != 1);
93 /* A paste succeeds if CR0 EQ bit is set */
94 FAIL_IF(paste(buf) & 0x20000000);
95 }
96 } else {
97 for (int i = 0; i < NUM_LOOPS; i++) {
98 FAIL_IF((read(fd1[READ_FD], &c, 1)) != 1);
99 copy(buf);
100 FAIL_IF((write(fd2[WRITE_FD], &c, 1) != 1));
101 }
102 }
103 return 0;
104
105}
106
107int main(int argc, char *argv[])
108{
109 return test_harness(test_cp_abort, "cp_abort");
110}
diff --git a/tools/testing/selftests/powerpc/mm/subpage_prot.c b/tools/testing/selftests/powerpc/mm/subpage_prot.c
index 440180ff8089..35ade7406dcd 100644
--- a/tools/testing/selftests/powerpc/mm/subpage_prot.c
+++ b/tools/testing/selftests/powerpc/mm/subpage_prot.c
@@ -73,7 +73,7 @@ static inline void check_faulted(void *addr, long page, long subpage, int write)
73 want_fault |= (subpage == ((page + 1) % 16)); 73 want_fault |= (subpage == ((page + 1) % 16));
74 74
75 if (faulted != want_fault) { 75 if (faulted != want_fault) {
76 printf("Failed at 0x%p (p=%ld,sp=%ld,w=%d), want=%s, got=%s !\n", 76 printf("Failed at %p (p=%ld,sp=%ld,w=%d), want=%s, got=%s !\n",
77 addr, page, subpage, write, 77 addr, page, subpage, write,
78 want_fault ? "fault" : "pass", 78 want_fault ? "fault" : "pass",
79 faulted ? "fault" : "pass"); 79 faulted ? "fault" : "pass");
@@ -82,7 +82,7 @@ static inline void check_faulted(void *addr, long page, long subpage, int write)
82 82
83 if (faulted) { 83 if (faulted) {
84 if (dar != addr) { 84 if (dar != addr) {
85 printf("Fault expected at 0x%p and happened at 0x%p !\n", 85 printf("Fault expected at %p and happened at %p !\n",
86 addr, dar); 86 addr, dar);
87 } 87 }
88 faulted = 0; 88 faulted = 0;
@@ -162,7 +162,7 @@ int test_anon(void)
162 162
163 mallocblock = (void *)align; 163 mallocblock = (void *)align;
164 164
165 printf("allocated malloc block of 0x%lx bytes at 0x%p\n", 165 printf("allocated malloc block of 0x%lx bytes at %p\n",
166 mallocsize, mallocblock); 166 mallocsize, mallocblock);
167 167
168 printf("testing malloc block...\n"); 168 printf("testing malloc block...\n");
@@ -197,7 +197,7 @@ int test_file(void)
197 perror("failed to map file"); 197 perror("failed to map file");
198 return 1; 198 return 1;
199 } 199 }
200 printf("allocated %s for 0x%lx bytes at 0x%p\n", 200 printf("allocated %s for 0x%lx bytes at %p\n",
201 file_name, filesize, fileblock); 201 file_name, filesize, fileblock);
202 202
203 printf("testing file map...\n"); 203 printf("testing file map...\n");
@@ -207,14 +207,16 @@ int test_file(void)
207 207
208int main(int argc, char *argv[]) 208int main(int argc, char *argv[])
209{ 209{
210 test_harness(test_anon, "subpage_prot_anon"); 210 int rc;
211
212 rc = test_harness(test_anon, "subpage_prot_anon");
213 if (rc)
214 return rc;
211 215
212 if (argc > 1) 216 if (argc > 1)
213 file_name = argv[1]; 217 file_name = argv[1];
214 else 218 else
215 file_name = "tempfile"; 219 file_name = "tempfile";
216 220
217 test_harness(test_file, "subpage_prot_file"); 221 return test_harness(test_file, "subpage_prot_file");
218
219 return 0;
220} 222}
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
index e67452f1bcff..46681fec549b 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
+++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
@@ -15,7 +15,6 @@
15#include <sys/ioctl.h> 15#include <sys/ioctl.h>
16 16
17#include "trace.h" 17#include "trace.h"
18#include "reg.h"
19#include "ebb.h" 18#include "ebb.h"
20 19
21 20
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c b/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c
index 5b1188f10c15..f923228bca22 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c
+++ b/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c
@@ -7,7 +7,6 @@
7#include <stdlib.h> 7#include <stdlib.h>
8 8
9#include "ebb.h" 9#include "ebb.h"
10#include "reg.h"
11 10
12 11
13/* 12/*
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/reg.h b/tools/testing/selftests/powerpc/reg.h
index 5921b0dfe2e9..65bfdeeebdee 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/reg.h
+++ b/tools/testing/selftests/powerpc/reg.h
@@ -9,12 +9,12 @@
9#define __stringify_1(x) #x 9#define __stringify_1(x) #x
10#define __stringify(x) __stringify_1(x) 10#define __stringify(x) __stringify_1(x)
11 11
12#define mfspr(rn) ({unsigned long rval; \ 12#define mfspr(rn) ({unsigned long rval; \
13 asm volatile("mfspr %0," __stringify(rn) \ 13 asm volatile("mfspr %0," _str(rn) \
14 : "=r" (rval)); rval; }) 14 : "=r" (rval)); rval; })
15#define mtspr(rn, v) asm volatile("mtspr " __stringify(rn) ",%0" : \ 15#define mtspr(rn, v) asm volatile("mtspr " _str(rn) ",%0" : \
16 : "r" ((unsigned long)(v)) \ 16 : "r" ((unsigned long)(v)) \
17 : "memory") 17 : "memory")
18 18
19#define mb() asm volatile("sync" : : : "memory"); 19#define mb() asm volatile("sync" : : : "memory");
20 20
@@ -46,4 +46,10 @@
46#define SPRN_SDAR 781 46#define SPRN_SDAR 781
47#define SPRN_SIER 768 47#define SPRN_SIER 768
48 48
49#define SPRN_TEXASR 0x82
50#define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */
51#define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */
52#define TEXASR_FS 0x08000000
53#define SPRN_TAR 0x32f
54
49#endif /* _SELFTESTS_POWERPC_REG_H */ 55#endif /* _SELFTESTS_POWERPC_REG_H */
diff --git a/tools/testing/selftests/powerpc/tm/.gitignore b/tools/testing/selftests/powerpc/tm/.gitignore
index 7d0f14b8cb2e..bb942db845bf 100644
--- a/tools/testing/selftests/powerpc/tm/.gitignore
+++ b/tools/testing/selftests/powerpc/tm/.gitignore
@@ -3,3 +3,6 @@ tm-syscall
3tm-signal-msr-resv 3tm-signal-msr-resv
4tm-signal-stack 4tm-signal-stack
5tm-vmxcopy 5tm-vmxcopy
6tm-fork
7tm-tar
8tm-tmspr
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 737f72c964e6..d0505dbd22d5 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -1,4 +1,4 @@
1TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack tm-vmxcopy 1TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack tm-vmxcopy tm-fork tm-tar tm-tmspr
2 2
3all: $(TEST_PROGS) 3all: $(TEST_PROGS)
4 4
@@ -6,6 +6,7 @@ $(TEST_PROGS): ../harness.c ../utils.c
6 6
7tm-syscall: tm-syscall-asm.S 7tm-syscall: tm-syscall-asm.S
8tm-syscall: CFLAGS += -mhtm -I../../../../../usr/include 8tm-syscall: CFLAGS += -mhtm -I../../../../../usr/include
9tm-tmspr: CFLAGS += -pthread
9 10
10include ../../lib.mk 11include ../../lib.mk
11 12
diff --git a/tools/testing/selftests/powerpc/tm/tm-fork.c b/tools/testing/selftests/powerpc/tm/tm-fork.c
new file mode 100644
index 000000000000..8d48579b7778
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-fork.c
@@ -0,0 +1,42 @@
1/*
2 * Copyright 2015, Michael Neuling, IBM Corp.
3 * Licensed under GPLv2.
4 *
5 * Edited: Rashmica Gupta, Nov 2015
6 *
7 * This test does a fork syscall inside a transaction. Basic sniff test
8 * to see if we can enter the kernel during a transaction.
9 */
10
11#include <errno.h>
12#include <inttypes.h>
13#include <pthread.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <unistd.h>
17
18#include "utils.h"
19#include "tm.h"
20
21int test_fork(void)
22{
23 SKIP_IF(!have_htm());
24
25 asm __volatile__(
26 "tbegin.;"
27 "blt 1f; "
28 "li 0, 2;" /* fork syscall */
29 "sc ;"
30 "tend.;"
31 "1: ;"
32 : : : "memory", "r0");
33 /* If we reach here, we've passed. Otherwise we've probably crashed
34 * the kernel */
35
36 return 0;
37}
38
39int main(int argc, char *argv[])
40{
41 return test_harness(test_fork, "tm_fork");
42}
diff --git a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
index 8fde93d6021f..d9c49f41515e 100644
--- a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
+++ b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
@@ -31,12 +31,6 @@
31#include "utils.h" 31#include "utils.h"
32#include "tm.h" 32#include "tm.h"
33 33
34#define TBEGIN ".long 0x7C00051D ;"
35#define TEND ".long 0x7C00055D ;"
36#define TCHECK ".long 0x7C00059C ;"
37#define TSUSPEND ".long 0x7C0005DD ;"
38#define TRESUME ".long 0x7C2005DD ;"
39#define SPRN_TEXASR 0x82
40#define SPRN_DSCR 0x03 34#define SPRN_DSCR 0x03
41 35
42int test_body(void) 36int test_body(void)
@@ -55,13 +49,13 @@ int test_body(void)
55 "mtspr %[sprn_dscr], 3;" 49 "mtspr %[sprn_dscr], 3;"
56 50
57 /* start and suspend a transaction */ 51 /* start and suspend a transaction */
58 TBEGIN 52 "tbegin.;"
59 "beq 1f;" 53 "beq 1f;"
60 TSUSPEND 54 "tsuspend.;"
61 55
62 /* hard loop until the transaction becomes doomed */ 56 /* hard loop until the transaction becomes doomed */
63 "2: ;" 57 "2: ;"
64 TCHECK 58 "tcheck 0;"
65 "bc 4, 0, 2b;" 59 "bc 4, 0, 2b;"
66 60
67 /* record DSCR and TEXASR */ 61 /* record DSCR and TEXASR */
@@ -70,8 +64,8 @@ int test_body(void)
70 "mfspr 3, %[sprn_texasr];" 64 "mfspr 3, %[sprn_texasr];"
71 "std 3, %[texasr];" 65 "std 3, %[texasr];"
72 66
73 TRESUME 67 "tresume.;"
74 TEND 68 "tend.;"
75 "li %[rv], 0;" 69 "li %[rv], 0;"
76 "1: ;" 70 "1: ;"
77 : [rv]"=r"(rv), [dscr2]"=m"(dscr2), [texasr]"=m"(texasr) 71 : [rv]"=r"(rv), [dscr2]"=m"(dscr2), [texasr]"=m"(texasr)
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-stack.c b/tools/testing/selftests/powerpc/tm/tm-signal-stack.c
index e44a238c1d77..1f0eb567438d 100644
--- a/tools/testing/selftests/powerpc/tm/tm-signal-stack.c
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-stack.c
@@ -60,9 +60,9 @@ int tm_signal_stack()
60 exit(1); 60 exit(1);
61 asm volatile("li 1, 0 ;" /* stack ptr == NULL */ 61 asm volatile("li 1, 0 ;" /* stack ptr == NULL */
62 "1:" 62 "1:"
63 ".long 0x7C00051D ;" /* tbegin */ 63 "tbegin.;"
64 "beq 1b ;" /* retry forever */ 64 "beq 1b ;" /* retry forever */
65 ".long 0x7C0005DD ; ;" /* tsuspend */ 65 "tsuspend.;"
66 "ld 2, 0(1) ;" /* trigger segv" */ 66 "ld 2, 0(1) ;" /* trigger segv" */
67 : : : "memory"); 67 : : : "memory");
68 68
diff --git a/tools/testing/selftests/powerpc/tm/tm-tar.c b/tools/testing/selftests/powerpc/tm/tm-tar.c
new file mode 100644
index 000000000000..2d2fcc2b7a60
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-tar.c
@@ -0,0 +1,90 @@
1/*
2 * Copyright 2015, Michael Neuling, IBM Corp.
3 * Licensed under GPLv2.
4 * Original: Michael Neuling 19/7/2013
5 * Edited: Rashmica Gupta 01/12/2015
6 *
7 * Do some transactions, see if the tar is corrupted.
8 * If the transaction is aborted, the TAR should be rolled back to the
9 * checkpointed value before the transaction began. The value written to
10 * TAR in suspended mode should only remain in TAR if the transaction
11 * completes.
12 */
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <unistd.h>
17#include <string.h>
18
19#include "tm.h"
20#include "utils.h"
21
22int num_loops = 10000;
23
24int test_tar(void)
25{
26 int i;
27
28 SKIP_IF(!have_htm());
29
30 for (i = 0; i < num_loops; i++)
31 {
32 uint64_t result = 0;
33 asm __volatile__(
34 "li 7, 1;"
35 "mtspr %[tar], 7;" /* tar = 1 */
36 "tbegin.;"
37 "beq 3f;"
38 "li 4, 0x7000;" /* Loop lots, to use time */
39 "2:;" /* Start loop */
40 "li 7, 2;"
41 "mtspr %[tar], 7;" /* tar = 2 */
42 "tsuspend.;"
43 "li 7, 3;"
44 "mtspr %[tar], 7;" /* tar = 3 */
45 "tresume.;"
46 "subi 4, 4, 1;"
47 "cmpdi 4, 0;"
48 "bne 2b;"
49 "tend.;"
50
51 /* Transaction sucess! TAR should be 3 */
52 "mfspr 7, %[tar];"
53 "ori %[res], 7, 4;" // res = 3|4 = 7
54 "b 4f;"
55
56 /* Abort handler. TAR should be rolled back to 1 */
57 "3:;"
58 "mfspr 7, %[tar];"
59 "ori %[res], 7, 8;" // res = 1|8 = 9
60 "4:;"
61
62 : [res]"=r"(result)
63 : [tar]"i"(SPRN_TAR)
64 : "memory", "r0", "r4", "r7");
65
66 /* If result is anything else other than 7 or 9, the tar
67 * value must have been corrupted. */
68 if ((result != 7) && (result != 9))
69 return 1;
70 }
71 return 0;
72}
73
74int main(int argc, char *argv[])
75{
76 /* A low number of iterations (eg 100) can cause a false pass */
77 if (argc > 1) {
78 if (strcmp(argv[1], "-h") == 0) {
79 printf("Syntax:\n\t%s [<num loops>]\n",
80 argv[0]);
81 return 1;
82 } else {
83 num_loops = atoi(argv[1]);
84 }
85 }
86
87 printf("Starting, %d loops\n", num_loops);
88
89 return test_harness(test_tar, "tm_tar");
90}
diff --git a/tools/testing/selftests/powerpc/tm/tm-tmspr.c b/tools/testing/selftests/powerpc/tm/tm-tmspr.c
new file mode 100644
index 000000000000..2bda81c7bf23
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-tmspr.c
@@ -0,0 +1,143 @@
1/*
2 * Copyright 2015, Michael Neuling, IBM Corp.
3 * Licensed under GPLv2.
4 *
5 * Original: Michael Neuling 3/4/2014
6 * Modified: Rashmica Gupta 8/12/2015
7 *
8 * Check if any of the Transaction Memory SPRs get corrupted.
9 * - TFIAR - stores address of location of transaction failure
10 * - TFHAR - stores address of software failure handler (if transaction
11 * fails)
12 * - TEXASR - lots of info about the transacion(s)
13 *
14 * (1) create more threads than cpus
15 * (2) in each thread:
16 * (a) set TFIAR and TFHAR a unique value
17 * (b) loop for awhile, continually checking to see if
18 * either register has been corrupted.
19 *
20 * (3) Loop:
21 * (a) begin transaction
22 * (b) abort transaction
23 * (c) check TEXASR to see if FS has been corrupted
24 *
25 */
26
27#define _GNU_SOURCE
28#include <stdio.h>
29#include <stdlib.h>
30#include <unistd.h>
31#include <pthread.h>
32#include <string.h>
33
34#include "utils.h"
35#include "tm.h"
36
37int num_loops = 10000;
38int passed = 1;
39
40void tfiar_tfhar(void *in)
41{
42 int i, cpu;
43 unsigned long tfhar, tfhar_rd, tfiar, tfiar_rd;
44 cpu_set_t cpuset;
45
46 CPU_ZERO(&cpuset);
47 cpu = (unsigned long)in >> 1;
48 CPU_SET(cpu, &cpuset);
49 sched_setaffinity(0, sizeof(cpuset), &cpuset);
50
51 /* TFIAR: Last bit has to be high so userspace can read register */
52 tfiar = ((unsigned long)in) + 1;
53 tfiar += 2;
54 mtspr(SPRN_TFIAR, tfiar);
55
56 /* TFHAR: Last two bits are reserved */
57 tfhar = ((unsigned long)in);
58 tfhar &= ~0x3UL;
59 tfhar += 4;
60 mtspr(SPRN_TFHAR, tfhar);
61
62 for (i = 0; i < num_loops; i++) {
63 tfhar_rd = mfspr(SPRN_TFHAR);
64 tfiar_rd = mfspr(SPRN_TFIAR);
65 if ( (tfhar != tfhar_rd) || (tfiar != tfiar_rd) ) {
66 passed = 0;
67 return;
68 }
69 }
70 return;
71}
72
73void texasr(void *in)
74{
75 unsigned long i;
76 uint64_t result = 0;
77
78 for (i = 0; i < num_loops; i++) {
79 asm __volatile__(
80 "tbegin.;"
81 "beq 3f ;"
82 "tabort. 0 ;"
83 "tend.;"
84
85 /* Abort handler */
86 "3: ;"
87 ::: "memory");
88
89 /* Check the TEXASR */
90 result = mfspr(SPRN_TEXASR);
91 if ((result & TEXASR_FS) == 0) {
92 passed = 0;
93 return;
94 }
95 }
96 return;
97}
98
99int test_tmspr()
100{
101 pthread_t thread;
102 int thread_num;
103 unsigned long i;
104
105 SKIP_IF(!have_htm());
106
107 /* To cause some context switching */
108 thread_num = 10 * sysconf(_SC_NPROCESSORS_ONLN);
109
110 /* Test TFIAR and TFHAR */
111 for (i = 0 ; i < thread_num ; i += 2){
112 if (pthread_create(&thread, NULL, (void*)tfiar_tfhar, (void *)i))
113 return EXIT_FAILURE;
114 }
115 if (pthread_join(thread, NULL) != 0)
116 return EXIT_FAILURE;
117
118 /* Test TEXASR */
119 for (i = 0 ; i < thread_num ; i++){
120 if (pthread_create(&thread, NULL, (void*)texasr, (void *)i))
121 return EXIT_FAILURE;
122 }
123 if (pthread_join(thread, NULL) != 0)
124 return EXIT_FAILURE;
125
126 if (passed)
127 return 0;
128 else
129 return 1;
130}
131
132int main(int argc, char *argv[])
133{
134 if (argc > 1) {
135 if (strcmp(argv[1], "-h") == 0) {
136 printf("Syntax:\t [<num loops>]\n");
137 return 0;
138 } else {
139 num_loops = atoi(argv[1]);
140 }
141 }
142 return test_harness(test_tmspr, "tm_tmspr");
143}
diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h
index 175ac6ad10dd..a985cfaa535e 100644
--- a/tools/testing/selftests/powerpc/utils.h
+++ b/tools/testing/selftests/powerpc/utils.h
@@ -6,9 +6,12 @@
6#ifndef _SELFTESTS_POWERPC_UTILS_H 6#ifndef _SELFTESTS_POWERPC_UTILS_H
7#define _SELFTESTS_POWERPC_UTILS_H 7#define _SELFTESTS_POWERPC_UTILS_H
8 8
9#define __cacheline_aligned __attribute__((aligned(128)))
10
9#include <stdint.h> 11#include <stdint.h>
10#include <stdbool.h> 12#include <stdbool.h>
11#include <linux/auxvec.h> 13#include <linux/auxvec.h>
14#include "reg.h"
12 15
13/* Avoid headaches with PRI?64 - just use %ll? always */ 16/* Avoid headaches with PRI?64 - just use %ll? always */
14typedef unsigned long long u64; 17typedef unsigned long long u64;
@@ -54,4 +57,9 @@ do { \
54#define _str(s) #s 57#define _str(s) #s
55#define str(s) _str(s) 58#define str(s) _str(s)
56 59
60/* POWER9 feature */
61#ifndef PPC_FEATURE2_ARCH_3_00
62#define PPC_FEATURE2_ARCH_3_00 0x00800000
63#endif
64
57#endif /* _SELFTESTS_POWERPC_UTILS_H */ 65#endif /* _SELFTESTS_POWERPC_UTILS_H */
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index 150829dd7998..2e58549b2f02 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -5,6 +5,7 @@
5 * Test code for seccomp bpf. 5 * Test code for seccomp bpf.
6 */ 6 */
7 7
8#include <sys/types.h>
8#include <asm/siginfo.h> 9#include <asm/siginfo.h>
9#define __have_siginfo_t 1 10#define __have_siginfo_t 1
10#define __have_sigval_t 1 11#define __have_sigval_t 1
@@ -14,7 +15,6 @@
14#include <linux/filter.h> 15#include <linux/filter.h>
15#include <sys/prctl.h> 16#include <sys/prctl.h>
16#include <sys/ptrace.h> 17#include <sys/ptrace.h>
17#include <sys/types.h>
18#include <sys/user.h> 18#include <sys/user.h>
19#include <linux/prctl.h> 19#include <linux/prctl.h>
20#include <linux/ptrace.h> 20#include <linux/ptrace.h>
@@ -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]
@@ -1242,6 +1246,12 @@ TEST_F(TRACE_poke, getpid_runs_normally)
1242# define ARCH_REGS s390_regs 1246# define ARCH_REGS s390_regs
1243# define SYSCALL_NUM gprs[2] 1247# define SYSCALL_NUM gprs[2]
1244# define SYSCALL_RET gprs[2] 1248# define SYSCALL_RET gprs[2]
1249#elif defined(__mips__)
1250# define ARCH_REGS struct pt_regs
1251# define SYSCALL_NUM regs[2]
1252# define SYSCALL_SYSCALL_NUM regs[4]
1253# define SYSCALL_RET regs[2]
1254# define SYSCALL_NUM_RET_SHARE_REG
1245#else 1255#else
1246# error "Do not know how to find your architecture's registers and syscalls" 1256# error "Do not know how to find your architecture's registers and syscalls"
1247#endif 1257#endif
@@ -1249,7 +1259,7 @@ TEST_F(TRACE_poke, getpid_runs_normally)
1249/* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for 1259/* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for
1250 * architectures without HAVE_ARCH_TRACEHOOK (e.g. User-mode Linux). 1260 * architectures without HAVE_ARCH_TRACEHOOK (e.g. User-mode Linux).
1251 */ 1261 */
1252#if defined(__x86_64__) || defined(__i386__) 1262#if defined(__x86_64__) || defined(__i386__) || defined(__mips__)
1253#define HAVE_GETREGS 1263#define HAVE_GETREGS
1254#endif 1264#endif
1255 1265
@@ -1273,6 +1283,10 @@ int get_syscall(struct __test_metadata *_metadata, pid_t tracee)
1273 } 1283 }
1274#endif 1284#endif
1275 1285
1286#if defined(__mips__)
1287 if (regs.SYSCALL_NUM == __NR_O32_Linux)
1288 return regs.SYSCALL_SYSCALL_NUM;
1289#endif
1276 return regs.SYSCALL_NUM; 1290 return regs.SYSCALL_NUM;
1277} 1291}
1278 1292
@@ -1293,10 +1307,17 @@ void change_syscall(struct __test_metadata *_metadata,
1293 EXPECT_EQ(0, ret); 1307 EXPECT_EQ(0, ret);
1294 1308
1295#if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \ 1309#if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \
1296 defined(__s390__) 1310 defined(__s390__) || defined(__hppa__)
1297 { 1311 {
1298 regs.SYSCALL_NUM = syscall; 1312 regs.SYSCALL_NUM = syscall;
1299 } 1313 }
1314#elif defined(__mips__)
1315 {
1316 if (regs.SYSCALL_NUM == __NR_O32_Linux)
1317 regs.SYSCALL_SYSCALL_NUM = syscall;
1318 else
1319 regs.SYSCALL_NUM = syscall;
1320 }
1300 1321
1301#elif defined(__arm__) 1322#elif defined(__arm__)
1302# ifndef PTRACE_SET_SYSCALL 1323# ifndef PTRACE_SET_SYSCALL
@@ -1327,7 +1348,11 @@ void change_syscall(struct __test_metadata *_metadata,
1327 1348
1328 /* If syscall is skipped, change return value. */ 1349 /* If syscall is skipped, change return value. */
1329 if (syscall == -1) 1350 if (syscall == -1)
1351#ifdef SYSCALL_NUM_RET_SHARE_REG
1352 TH_LOG("Can't modify syscall return on this architecture");
1353#else
1330 regs.SYSCALL_RET = 1; 1354 regs.SYSCALL_RET = 1;
1355#endif
1331 1356
1332#ifdef HAVE_GETREGS 1357#ifdef HAVE_GETREGS
1333 ret = ptrace(PTRACE_SETREGS, tracee, 0, &regs); 1358 ret = ptrace(PTRACE_SETREGS, tracee, 0, &regs);
@@ -1465,8 +1490,13 @@ TEST_F(TRACE_syscall, syscall_dropped)
1465 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0); 1490 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
1466 ASSERT_EQ(0, ret); 1491 ASSERT_EQ(0, ret);
1467 1492
1493#ifdef SYSCALL_NUM_RET_SHARE_REG
1494 /* gettid has been skipped */
1495 EXPECT_EQ(-1, syscall(__NR_gettid));
1496#else
1468 /* gettid has been skipped and an altered return value stored. */ 1497 /* gettid has been skipped and an altered return value stored. */
1469 EXPECT_EQ(1, syscall(__NR_gettid)); 1498 EXPECT_EQ(1, syscall(__NR_gettid));
1499#endif
1470 EXPECT_NE(self->mytid, syscall(__NR_gettid)); 1500 EXPECT_NE(self->mytid, syscall(__NR_gettid));
1471} 1501}
1472 1502
@@ -1479,6 +1509,8 @@ TEST_F(TRACE_syscall, syscall_dropped)
1479# define __NR_seccomp 383 1509# define __NR_seccomp 383
1480# elif defined(__aarch64__) 1510# elif defined(__aarch64__)
1481# define __NR_seccomp 277 1511# define __NR_seccomp 277
1512# elif defined(__hppa__)
1513# define __NR_seccomp 338
1482# elif defined(__powerpc__) 1514# elif defined(__powerpc__)
1483# define __NR_seccomp 358 1515# define __NR_seccomp 358
1484# elif defined(__s390__) 1516# elif defined(__s390__)
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/usb/usbip/libsrc/Makefile.am b/tools/usb/usbip/libsrc/Makefile.am
index 7c8f8a4d54e4..90daf95c0804 100644
--- a/tools/usb/usbip/libsrc/Makefile.am
+++ b/tools/usb/usbip/libsrc/Makefile.am
@@ -4,5 +4,7 @@ libusbip_la_LDFLAGS = -version-info @LIBUSBIP_VERSION@
4 4
5lib_LTLIBRARIES := libusbip.la 5lib_LTLIBRARIES := libusbip.la
6libusbip_la_SOURCES := names.c names.h usbip_host_driver.c usbip_host_driver.h \ 6libusbip_la_SOURCES := names.c names.h usbip_host_driver.c usbip_host_driver.h \
7 usbip_common.c usbip_common.h vhci_driver.c vhci_driver.h \ 7 usbip_device_driver.c usbip_device_driver.h \
8 usbip_common.c usbip_common.h usbip_host_common.h \
9 usbip_host_common.c vhci_driver.c vhci_driver.h \
8 sysfs_utils.c sysfs_utils.h 10 sysfs_utils.c sysfs_utils.h
diff --git a/tools/usb/usbip/libsrc/usbip_common.h b/tools/usb/usbip/libsrc/usbip_common.h
index 15fe792e1e96..51ef5fe485dd 100644
--- a/tools/usb/usbip/libsrc/usbip_common.h
+++ b/tools/usb/usbip/libsrc/usbip_common.h
@@ -25,9 +25,12 @@
25#define VHCI_STATE_PATH "/var/run/vhci_hcd" 25#define VHCI_STATE_PATH "/var/run/vhci_hcd"
26#endif 26#endif
27 27
28#define VUDC_DEVICE_DESCR_FILE "dev_desc"
29
28/* kernel module names */ 30/* kernel module names */
29#define USBIP_CORE_MOD_NAME "usbip-core" 31#define USBIP_CORE_MOD_NAME "usbip-core"
30#define USBIP_HOST_DRV_NAME "usbip-host" 32#define USBIP_HOST_DRV_NAME "usbip-host"
33#define USBIP_DEVICE_DRV_NAME "usbip-vudc"
31#define USBIP_VHCI_DRV_NAME "vhci_hcd" 34#define USBIP_VHCI_DRV_NAME "vhci_hcd"
32 35
33/* sysfs constants */ 36/* sysfs constants */
diff --git a/tools/usb/usbip/libsrc/usbip_device_driver.c b/tools/usb/usbip/libsrc/usbip_device_driver.c
new file mode 100644
index 000000000000..e059b7d1ec5b
--- /dev/null
+++ b/tools/usb/usbip/libsrc/usbip_device_driver.c
@@ -0,0 +1,163 @@
1/*
2 * Copyright (C) 2015 Karol Kosik <karo9@interia.eu>
3 * 2015 Samsung Electronics
4 * Author: Igor Kotrasinski <i.kotrasinsk@samsung.com>
5 *
6 * Based on tools/usb/usbip/libsrc/usbip_host_driver.c, which is:
7 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
8 * 2005-2007 Takahiro Hirofuchi
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24#include <fcntl.h>
25#include <string.h>
26#include <linux/usb/ch9.h>
27
28#include <unistd.h>
29
30#include "usbip_host_common.h"
31#include "usbip_device_driver.h"
32
33#undef PROGNAME
34#define PROGNAME "libusbip"
35
36#define copy_descr_attr16(dev, descr, attr) \
37 ((dev)->attr = le16toh((descr)->attr)) \
38
39#define copy_descr_attr(dev, descr, attr) \
40 ((dev)->attr = (descr)->attr) \
41
42#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
43
44static struct {
45 enum usb_device_speed speed;
46 const char *name;
47} speed_names[] = {
48 {
49 .speed = USB_SPEED_UNKNOWN,
50 .name = "UNKNOWN",
51 },
52 {
53 .speed = USB_SPEED_LOW,
54 .name = "low-speed",
55 },
56 {
57 .speed = USB_SPEED_FULL,
58 .name = "full-speed",
59 },
60 {
61 .speed = USB_SPEED_HIGH,
62 .name = "high-speed",
63 },
64 {
65 .speed = USB_SPEED_WIRELESS,
66 .name = "wireless",
67 },
68 {
69 .speed = USB_SPEED_SUPER,
70 .name = "super-speed",
71 },
72};
73
74static
75int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev)
76{
77 const char *path, *name;
78 char filepath[SYSFS_PATH_MAX];
79 struct usb_device_descriptor descr;
80 unsigned i;
81 FILE *fd = NULL;
82 struct udev_device *plat;
83 const char *speed;
84 int ret = 0;
85
86 plat = udev_device_get_parent(sdev);
87 path = udev_device_get_syspath(plat);
88 snprintf(filepath, SYSFS_PATH_MAX, "%s/%s",
89 path, VUDC_DEVICE_DESCR_FILE);
90 fd = fopen(filepath, "r");
91 if (!fd)
92 return -1;
93 ret = fread((char *) &descr, sizeof(descr), 1, fd);
94 if (ret < 0)
95 return -1;
96 fclose(fd);
97
98 copy_descr_attr(dev, &descr, bDeviceClass);
99 copy_descr_attr(dev, &descr, bDeviceSubClass);
100 copy_descr_attr(dev, &descr, bDeviceProtocol);
101 copy_descr_attr(dev, &descr, bNumConfigurations);
102 copy_descr_attr16(dev, &descr, idVendor);
103 copy_descr_attr16(dev, &descr, idProduct);
104 copy_descr_attr16(dev, &descr, bcdDevice);
105
106 strncpy(dev->path, path, SYSFS_PATH_MAX);
107
108 dev->speed = USB_SPEED_UNKNOWN;
109 speed = udev_device_get_sysattr_value(sdev, "current_speed");
110 if (speed) {
111 for (i = 0; i < ARRAY_SIZE(speed_names); i++) {
112 if (!strcmp(speed_names[i].name, speed)) {
113 dev->speed = speed_names[i].speed;
114 break;
115 }
116 }
117 }
118
119 /* Only used for user output, little sense to output them in general */
120 dev->bNumInterfaces = 0;
121 dev->bConfigurationValue = 0;
122 dev->busnum = 0;
123
124 name = udev_device_get_sysname(plat);
125 strncpy(dev->busid, name, SYSFS_BUS_ID_SIZE);
126 return 0;
127}
128
129static int is_my_device(struct udev_device *dev)
130{
131 const char *driver;
132
133 driver = udev_device_get_property_value(dev, "USB_UDC_NAME");
134 return driver != NULL && !strcmp(driver, USBIP_DEVICE_DRV_NAME);
135}
136
137static int usbip_device_driver_open(struct usbip_host_driver *hdriver)
138{
139 int ret;
140
141 hdriver->ndevs = 0;
142 INIT_LIST_HEAD(&hdriver->edev_list);
143
144 ret = usbip_generic_driver_open(hdriver);
145 if (ret)
146 err("please load " USBIP_CORE_MOD_NAME ".ko and "
147 USBIP_DEVICE_DRV_NAME ".ko!");
148
149 return ret;
150}
151
152struct usbip_host_driver device_driver = {
153 .edev_list = LIST_HEAD_INIT(device_driver.edev_list),
154 .udev_subsystem = "udc",
155 .ops = {
156 .open = usbip_device_driver_open,
157 .close = usbip_generic_driver_close,
158 .refresh_device_list = usbip_generic_refresh_device_list,
159 .get_device = usbip_generic_get_device,
160 .read_device = read_usb_vudc_device,
161 .is_my_device = is_my_device,
162 },
163};
diff --git a/tools/usb/usbip/libsrc/usbip_device_driver.h b/tools/usb/usbip/libsrc/usbip_device_driver.h
new file mode 100644
index 000000000000..54cb658b37a3
--- /dev/null
+++ b/tools/usb/usbip/libsrc/usbip_device_driver.h
@@ -0,0 +1,34 @@
1/*
2 * Copyright (C) 2015 Karol Kosik <karo9@interia.eu>
3 * 2015 Samsung Electronics
4 * Author: Igor Kotrasinski <i.kotrasinsk@samsung.com>
5 *
6 * Based on tools/usb/usbip/libsrc/usbip_host_driver.c, which is:
7 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
8 * 2005-2007 Takahiro Hirofuchi
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24#ifndef __USBIP_DEVICE_DRIVER_H
25#define __USBIP_DEVICE_DRIVER_H
26
27#include <stdint.h>
28#include "usbip_common.h"
29#include "usbip_host_common.h"
30#include "list.h"
31
32extern struct usbip_host_driver device_driver;
33
34#endif /* __USBIP_DEVICE_DRIVER_H */
diff --git a/tools/usb/usbip/libsrc/usbip_host_common.c b/tools/usb/usbip/libsrc/usbip_host_common.c
new file mode 100644
index 000000000000..9d415228883d
--- /dev/null
+++ b/tools/usb/usbip/libsrc/usbip_host_common.c
@@ -0,0 +1,273 @@
1/*
2 * Copyright (C) 2015-2016 Samsung Electronics
3 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
4 * Krzysztof Opasiak <k.opasiak@samsung.com>
5 *
6 * Refactored from usbip_host_driver.c, which is:
7 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
8 * 2005-2007 Takahiro Hirofuchi
9 *
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <fcntl.h>
27
28#include <errno.h>
29#include <unistd.h>
30
31#include <libudev.h>
32
33#include "usbip_common.h"
34#include "usbip_host_common.h"
35#include "list.h"
36#include "sysfs_utils.h"
37
38struct udev *udev_context;
39
40static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
41{
42 char status_attr_path[SYSFS_PATH_MAX];
43 int fd;
44 int length;
45 char status;
46 int value = 0;
47
48 snprintf(status_attr_path, SYSFS_PATH_MAX, "%s/usbip_status",
49 udev->path);
50
51 fd = open(status_attr_path, O_RDONLY);
52 if (fd < 0) {
53 err("error opening attribute %s", status_attr_path);
54 return -1;
55 }
56
57 length = read(fd, &status, 1);
58 if (length < 0) {
59 err("error reading attribute %s", status_attr_path);
60 close(fd);
61 return -1;
62 }
63
64 value = atoi(&status);
65
66 return value;
67}
68
69static
70struct usbip_exported_device *usbip_exported_device_new(
71 struct usbip_host_driver *hdriver, const char *sdevpath)
72{
73 struct usbip_exported_device *edev = NULL;
74 struct usbip_exported_device *edev_old;
75 size_t size;
76 int i;
77
78 edev = calloc(1, sizeof(struct usbip_exported_device));
79
80 edev->sudev =
81 udev_device_new_from_syspath(udev_context, sdevpath);
82 if (!edev->sudev) {
83 err("udev_device_new_from_syspath: %s", sdevpath);
84 goto err;
85 }
86
87 if (hdriver->ops.read_device(edev->sudev, &edev->udev) < 0)
88 goto err;
89
90 edev->status = read_attr_usbip_status(&edev->udev);
91 if (edev->status < 0)
92 goto err;
93
94 /* reallocate buffer to include usb interface data */
95 size = sizeof(struct usbip_exported_device) +
96 edev->udev.bNumInterfaces * sizeof(struct usbip_usb_interface);
97
98 edev_old = edev;
99 edev = realloc(edev, size);
100 if (!edev) {
101 edev = edev_old;
102 dbg("realloc failed");
103 goto err;
104 }
105
106 for (i = 0; i < edev->udev.bNumInterfaces; i++) {
107 /* vudc does not support reading interfaces */
108 if (!hdriver->ops.read_interface)
109 break;
110 hdriver->ops.read_interface(&edev->udev, i, &edev->uinf[i]);
111 }
112
113 return edev;
114err:
115 if (edev->sudev)
116 udev_device_unref(edev->sudev);
117 if (edev)
118 free(edev);
119
120 return NULL;
121}
122
123static int refresh_exported_devices(struct usbip_host_driver *hdriver)
124{
125 struct usbip_exported_device *edev;
126 struct udev_enumerate *enumerate;
127 struct udev_list_entry *devices, *dev_list_entry;
128 struct udev_device *dev;
129 const char *path;
130
131 enumerate = udev_enumerate_new(udev_context);
132 udev_enumerate_add_match_subsystem(enumerate, hdriver->udev_subsystem);
133 udev_enumerate_scan_devices(enumerate);
134
135 devices = udev_enumerate_get_list_entry(enumerate);
136
137 udev_list_entry_foreach(dev_list_entry, devices) {
138 path = udev_list_entry_get_name(dev_list_entry);
139 dev = udev_device_new_from_syspath(udev_context,
140 path);
141 if (dev == NULL)
142 continue;
143
144 /* Check whether device uses usbip driver. */
145 if (hdriver->ops.is_my_device(dev)) {
146 edev = usbip_exported_device_new(hdriver, path);
147 if (!edev) {
148 dbg("usbip_exported_device_new failed");
149 continue;
150 }
151
152 list_add(&edev->node, &hdriver->edev_list);
153 hdriver->ndevs++;
154 }
155 }
156
157 return 0;
158}
159
160static void usbip_exported_device_destroy(struct list_head *devs)
161{
162 struct list_head *i, *tmp;
163 struct usbip_exported_device *edev;
164
165 list_for_each_safe(i, tmp, devs) {
166 edev = list_entry(i, struct usbip_exported_device, node);
167 list_del(i);
168 free(edev);
169 }
170}
171
172int usbip_generic_driver_open(struct usbip_host_driver *hdriver)
173{
174 int rc;
175
176 udev_context = udev_new();
177 if (!udev_context) {
178 err("udev_new failed");
179 return -1;
180 }
181
182 rc = refresh_exported_devices(hdriver);
183 if (rc < 0)
184 goto err;
185 return 0;
186err:
187 udev_unref(udev_context);
188 return -1;
189}
190
191void usbip_generic_driver_close(struct usbip_host_driver *hdriver)
192{
193 if (!hdriver)
194 return;
195
196 usbip_exported_device_destroy(&hdriver->edev_list);
197
198 udev_unref(udev_context);
199}
200
201int usbip_generic_refresh_device_list(struct usbip_host_driver *hdriver)
202{
203 int rc;
204
205 usbip_exported_device_destroy(&hdriver->edev_list);
206
207 hdriver->ndevs = 0;
208 INIT_LIST_HEAD(&hdriver->edev_list);
209
210 rc = refresh_exported_devices(hdriver);
211 if (rc < 0)
212 return -1;
213
214 return 0;
215}
216
217int usbip_export_device(struct usbip_exported_device *edev, int sockfd)
218{
219 char attr_name[] = "usbip_sockfd";
220 char sockfd_attr_path[SYSFS_PATH_MAX];
221 char sockfd_buff[30];
222 int ret;
223
224 if (edev->status != SDEV_ST_AVAILABLE) {
225 dbg("device not available: %s", edev->udev.busid);
226 switch (edev->status) {
227 case SDEV_ST_ERROR:
228 dbg("status SDEV_ST_ERROR");
229 break;
230 case SDEV_ST_USED:
231 dbg("status SDEV_ST_USED");
232 break;
233 default:
234 dbg("status unknown: 0x%x", edev->status);
235 }
236 return -1;
237 }
238
239 /* only the first interface is true */
240 snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s",
241 edev->udev.path, attr_name);
242
243 snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
244
245 ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff,
246 strlen(sockfd_buff));
247 if (ret < 0) {
248 err("write_sysfs_attribute failed: sockfd %s to %s",
249 sockfd_buff, sockfd_attr_path);
250 return ret;
251 }
252
253 info("connect: %s", edev->udev.busid);
254
255 return ret;
256}
257
258struct usbip_exported_device *usbip_generic_get_device(
259 struct usbip_host_driver *hdriver, int num)
260{
261 struct list_head *i;
262 struct usbip_exported_device *edev;
263 int cnt = 0;
264
265 list_for_each(i, &hdriver->edev_list) {
266 edev = list_entry(i, struct usbip_exported_device, node);
267 if (num == cnt)
268 return edev;
269 cnt++;
270 }
271
272 return NULL;
273}
diff --git a/tools/usb/usbip/libsrc/usbip_host_common.h b/tools/usb/usbip/libsrc/usbip_host_common.h
new file mode 100644
index 000000000000..a64b8033fe64
--- /dev/null
+++ b/tools/usb/usbip/libsrc/usbip_host_common.h
@@ -0,0 +1,104 @@
1/*
2 * Copyright (C) 2015-2016 Samsung Electronics
3 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
4 * Krzysztof Opasiak <k.opasiak@samsung.com>
5 *
6 * Refactored from usbip_host_driver.c, which is:
7 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
8 * 2005-2007 Takahiro Hirofuchi
9 *
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24#ifndef __USBIP_HOST_COMMON_H
25#define __USBIP_HOST_COMMON_H
26
27#include <stdint.h>
28#include <libudev.h>
29#include <errno.h>
30#include "list.h"
31#include "usbip_common.h"
32#include "sysfs_utils.h"
33
34struct usbip_host_driver;
35
36struct usbip_host_driver_ops {
37 int (*open)(struct usbip_host_driver *hdriver);
38 void (*close)(struct usbip_host_driver *hdriver);
39 int (*refresh_device_list)(struct usbip_host_driver *hdriver);
40 struct usbip_exported_device * (*get_device)(
41 struct usbip_host_driver *hdriver, int num);
42
43 int (*read_device)(struct udev_device *sdev,
44 struct usbip_usb_device *dev);
45 int (*read_interface)(struct usbip_usb_device *udev, int i,
46 struct usbip_usb_interface *uinf);
47 int (*is_my_device)(struct udev_device *udev);
48};
49
50struct usbip_host_driver {
51 int ndevs;
52 /* list of exported device */
53 struct list_head edev_list;
54 const char *udev_subsystem;
55 struct usbip_host_driver_ops ops;
56};
57
58struct usbip_exported_device {
59 struct udev_device *sudev;
60 int32_t status;
61 struct usbip_usb_device udev;
62 struct list_head node;
63 struct usbip_usb_interface uinf[];
64};
65
66/* External API to access the driver */
67static inline int usbip_driver_open(struct usbip_host_driver *hdriver)
68{
69 if (!hdriver->ops.open)
70 return -EOPNOTSUPP;
71 return hdriver->ops.open(hdriver);
72}
73
74static inline void usbip_driver_close(struct usbip_host_driver *hdriver)
75{
76 if (!hdriver->ops.close)
77 return;
78 hdriver->ops.close(hdriver);
79}
80
81static inline int usbip_refresh_device_list(struct usbip_host_driver *hdriver)
82{
83 if (!hdriver->ops.refresh_device_list)
84 return -EOPNOTSUPP;
85 return hdriver->ops.refresh_device_list(hdriver);
86}
87
88static inline struct usbip_exported_device *
89usbip_get_device(struct usbip_host_driver *hdriver, int num)
90{
91 if (!hdriver->ops.get_device)
92 return NULL;
93 return hdriver->ops.get_device(hdriver, num);
94}
95
96/* Helper functions for implementing driver backend */
97int usbip_generic_driver_open(struct usbip_host_driver *hdriver);
98void usbip_generic_driver_close(struct usbip_host_driver *hdriver);
99int usbip_generic_refresh_device_list(struct usbip_host_driver *hdriver);
100int usbip_export_device(struct usbip_exported_device *edev, int sockfd);
101struct usbip_exported_device *usbip_generic_get_device(
102 struct usbip_host_driver *hdriver, int num);
103
104#endif /* __USBIP_HOST_COMMON_H */
diff --git a/tools/usb/usbip/libsrc/usbip_host_driver.c b/tools/usb/usbip/libsrc/usbip_host_driver.c
index bef08d5c44e8..4de6edc54d35 100644
--- a/tools/usb/usbip/libsrc/usbip_host_driver.c
+++ b/tools/usb/usbip/libsrc/usbip_host_driver.c
@@ -1,6 +1,9 @@
1/* 1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi 3 * 2005-2007 Takahiro Hirofuchi
4 * Copyright (C) 2015-2016 Samsung Electronics
5 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
6 * Krzysztof Opasiak <k.opasiak@samsung.com>
4 * 7 *
5 * This program is free software: you can redistribute it and/or modify 8 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
@@ -16,265 +19,47 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */ 20 */
18 21
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <fcntl.h>
22
23#include <errno.h>
24#include <unistd.h> 22#include <unistd.h>
25
26#include <libudev.h> 23#include <libudev.h>
27 24
28#include "usbip_common.h" 25#include "usbip_host_common.h"
29#include "usbip_host_driver.h" 26#include "usbip_host_driver.h"
30#include "list.h"
31#include "sysfs_utils.h"
32 27
33#undef PROGNAME 28#undef PROGNAME
34#define PROGNAME "libusbip" 29#define PROGNAME "libusbip"
35 30
36struct usbip_host_driver *host_driver; 31static int is_my_device(struct udev_device *dev)
37struct udev *udev_context;
38
39static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
40{
41 char status_attr_path[SYSFS_PATH_MAX];
42 int fd;
43 int length;
44 char status;
45 int value = 0;
46
47 snprintf(status_attr_path, SYSFS_PATH_MAX, "%s/usbip_status",
48 udev->path);
49
50 fd = open(status_attr_path, O_RDONLY);
51 if (fd < 0) {
52 err("error opening attribute %s", status_attr_path);
53 return -1;
54 }
55
56 length = read(fd, &status, 1);
57 if (length < 0) {
58 err("error reading attribute %s", status_attr_path);
59 close(fd);
60 return -1;
61 }
62
63 value = atoi(&status);
64
65 return value;
66}
67
68static
69struct usbip_exported_device *usbip_exported_device_new(const char *sdevpath)
70{
71 struct usbip_exported_device *edev = NULL;
72 struct usbip_exported_device *edev_old;
73 size_t size;
74 int i;
75
76 edev = calloc(1, sizeof(struct usbip_exported_device));
77
78 edev->sudev = udev_device_new_from_syspath(udev_context, sdevpath);
79 if (!edev->sudev) {
80 err("udev_device_new_from_syspath: %s", sdevpath);
81 goto err;
82 }
83
84 read_usb_device(edev->sudev, &edev->udev);
85
86 edev->status = read_attr_usbip_status(&edev->udev);
87 if (edev->status < 0)
88 goto err;
89
90 /* reallocate buffer to include usb interface data */
91 size = sizeof(struct usbip_exported_device) +
92 edev->udev.bNumInterfaces * sizeof(struct usbip_usb_interface);
93
94 edev_old = edev;
95 edev = realloc(edev, size);
96 if (!edev) {
97 edev = edev_old;
98 dbg("realloc failed");
99 goto err;
100 }
101
102 for (i = 0; i < edev->udev.bNumInterfaces; i++)
103 read_usb_interface(&edev->udev, i, &edev->uinf[i]);
104
105 return edev;
106err:
107 if (edev->sudev)
108 udev_device_unref(edev->sudev);
109 if (edev)
110 free(edev);
111
112 return NULL;
113}
114
115static int refresh_exported_devices(void)
116{ 32{
117 struct usbip_exported_device *edev;
118 struct udev_enumerate *enumerate;
119 struct udev_list_entry *devices, *dev_list_entry;
120 struct udev_device *dev;
121 const char *path;
122 const char *driver; 33 const char *driver;
123 34
124 enumerate = udev_enumerate_new(udev_context); 35 driver = udev_device_get_driver(dev);
125 udev_enumerate_add_match_subsystem(enumerate, "usb"); 36 return driver != NULL && !strcmp(driver, USBIP_HOST_DRV_NAME);
126 udev_enumerate_scan_devices(enumerate);
127
128 devices = udev_enumerate_get_list_entry(enumerate);
129
130 udev_list_entry_foreach(dev_list_entry, devices) {
131 path = udev_list_entry_get_name(dev_list_entry);
132 dev = udev_device_new_from_syspath(udev_context, path);
133 if (dev == NULL)
134 continue;
135
136 /* Check whether device uses usbip-host driver. */
137 driver = udev_device_get_driver(dev);
138 if (driver != NULL && !strcmp(driver, USBIP_HOST_DRV_NAME)) {
139 edev = usbip_exported_device_new(path);
140 if (!edev) {
141 dbg("usbip_exported_device_new failed");
142 continue;
143 }
144
145 list_add(&edev->node, &host_driver->edev_list);
146 host_driver->ndevs++;
147 }
148 }
149
150 return 0;
151}
152
153static void usbip_exported_device_destroy(void)
154{
155 struct list_head *i, *tmp;
156 struct usbip_exported_device *edev;
157
158 list_for_each_safe(i, tmp, &host_driver->edev_list) {
159 edev = list_entry(i, struct usbip_exported_device, node);
160 list_del(i);
161 free(edev);
162 }
163} 37}
164 38
165int usbip_host_driver_open(void) 39static int usbip_host_driver_open(struct usbip_host_driver *hdriver)
166{ 40{
167 int rc;
168
169 udev_context = udev_new();
170 if (!udev_context) {
171 err("udev_new failed");
172 return -1;
173 }
174
175 host_driver = calloc(1, sizeof(*host_driver));
176
177 host_driver->ndevs = 0;
178 INIT_LIST_HEAD(&host_driver->edev_list);
179
180 rc = refresh_exported_devices();
181 if (rc < 0)
182 goto err_free_host_driver;
183
184 return 0;
185
186err_free_host_driver:
187 free(host_driver);
188 host_driver = NULL;
189
190 udev_unref(udev_context);
191
192 return -1;
193}
194
195void usbip_host_driver_close(void)
196{
197 if (!host_driver)
198 return;
199
200 usbip_exported_device_destroy();
201
202 free(host_driver);
203 host_driver = NULL;
204
205 udev_unref(udev_context);
206}
207
208int usbip_host_refresh_device_list(void)
209{
210 int rc;
211
212 usbip_exported_device_destroy();
213
214 host_driver->ndevs = 0;
215 INIT_LIST_HEAD(&host_driver->edev_list);
216
217 rc = refresh_exported_devices();
218 if (rc < 0)
219 return -1;
220
221 return 0;
222}
223
224int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd)
225{
226 char attr_name[] = "usbip_sockfd";
227 char sockfd_attr_path[SYSFS_PATH_MAX];
228 char sockfd_buff[30];
229 int ret; 41 int ret;
230 42
231 if (edev->status != SDEV_ST_AVAILABLE) { 43 hdriver->ndevs = 0;
232 dbg("device not available: %s", edev->udev.busid); 44 INIT_LIST_HEAD(&hdriver->edev_list);
233 switch (edev->status) {
234 case SDEV_ST_ERROR:
235 dbg("status SDEV_ST_ERROR");
236 break;
237 case SDEV_ST_USED:
238 dbg("status SDEV_ST_USED");
239 break;
240 default:
241 dbg("status unknown: 0x%x", edev->status);
242 }
243 return -1;
244 }
245
246 /* only the first interface is true */
247 snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s",
248 edev->udev.path, attr_name);
249
250 snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
251
252 ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff,
253 strlen(sockfd_buff));
254 if (ret < 0) {
255 err("write_sysfs_attribute failed: sockfd %s to %s",
256 sockfd_buff, sockfd_attr_path);
257 return ret;
258 }
259
260 info("connect: %s", edev->udev.busid);
261 45
46 ret = usbip_generic_driver_open(hdriver);
47 if (ret)
48 err("please load " USBIP_CORE_MOD_NAME ".ko and "
49 USBIP_HOST_DRV_NAME ".ko!");
262 return ret; 50 return ret;
263} 51}
264 52
265struct usbip_exported_device *usbip_host_get_device(int num) 53struct usbip_host_driver host_driver = {
266{ 54 .edev_list = LIST_HEAD_INIT(host_driver.edev_list),
267 struct list_head *i; 55 .udev_subsystem = "usb",
268 struct usbip_exported_device *edev; 56 .ops = {
269 int cnt = 0; 57 .open = usbip_host_driver_open,
270 58 .close = usbip_generic_driver_close,
271 list_for_each(i, &host_driver->edev_list) { 59 .refresh_device_list = usbip_generic_refresh_device_list,
272 edev = list_entry(i, struct usbip_exported_device, node); 60 .get_device = usbip_generic_get_device,
273 if (num == cnt) 61 .read_device = read_usb_device,
274 return edev; 62 .read_interface = read_usb_interface,
275 else 63 .is_my_device = is_my_device,
276 cnt++; 64 },
277 } 65};
278
279 return NULL;
280}
diff --git a/tools/usb/usbip/libsrc/usbip_host_driver.h b/tools/usb/usbip/libsrc/usbip_host_driver.h
index 2a31f855c616..77f07e72a7fe 100644
--- a/tools/usb/usbip/libsrc/usbip_host_driver.h
+++ b/tools/usb/usbip/libsrc/usbip_host_driver.h
@@ -1,6 +1,9 @@
1/* 1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi 3 * 2005-2007 Takahiro Hirofuchi
4 * Copyright (C) 2015-2016 Samsung Electronics
5 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
6 * Krzysztof Opasiak <k.opasiak@samsung.com>
4 * 7 *
5 * This program is free software: you can redistribute it and/or modify 8 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
@@ -22,28 +25,8 @@
22#include <stdint.h> 25#include <stdint.h>
23#include "usbip_common.h" 26#include "usbip_common.h"
24#include "list.h" 27#include "list.h"
28#include "usbip_host_common.h"
25 29
26struct usbip_host_driver { 30extern struct usbip_host_driver host_driver;
27 int ndevs;
28 /* list of exported device */
29 struct list_head edev_list;
30};
31
32struct usbip_exported_device {
33 struct udev_device *sudev;
34 int32_t status;
35 struct usbip_usb_device udev;
36 struct list_head node;
37 struct usbip_usb_interface uinf[];
38};
39
40extern struct usbip_host_driver *host_driver;
41
42int usbip_host_driver_open(void);
43void usbip_host_driver_close(void);
44
45int usbip_host_refresh_device_list(void);
46int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd);
47struct usbip_exported_device *usbip_host_get_device(int num);
48 31
49#endif /* __USBIP_HOST_DRIVER_H */ 32#endif /* __USBIP_HOST_DRIVER_H */
diff --git a/tools/usb/usbip/src/usbip_attach.c b/tools/usb/usbip/src/usbip_attach.c
index d58a14dfc094..70a6b507fb62 100644
--- a/tools/usb/usbip/src/usbip_attach.c
+++ b/tools/usb/usbip/src/usbip_attach.c
@@ -1,6 +1,9 @@
1/* 1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi 3 * 2005-2007 Takahiro Hirofuchi
4 * Copyright (C) 2015-2016 Samsung Electronics
5 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
6 * Krzysztof Opasiak <k.opasiak@samsung.com>
4 * 7 *
5 * This program is free software: you can redistribute it and/or modify 8 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
@@ -36,7 +39,8 @@
36static const char usbip_attach_usage_string[] = 39static const char usbip_attach_usage_string[] =
37 "usbip attach <args>\n" 40 "usbip attach <args>\n"
38 " -r, --remote=<host> The machine with exported USB devices\n" 41 " -r, --remote=<host> The machine with exported USB devices\n"
39 " -b, --busid=<busid> Busid of the device on <host>\n"; 42 " -b, --busid=<busid> Busid of the device on <host>\n"
43 " -d, --device=<devid> Id of the virtual UDC on <host>\n";
40 44
41void usbip_attach_usage(void) 45void usbip_attach_usage(void)
42{ 46{
@@ -203,6 +207,7 @@ int usbip_attach(int argc, char *argv[])
203 static const struct option opts[] = { 207 static const struct option opts[] = {
204 { "remote", required_argument, NULL, 'r' }, 208 { "remote", required_argument, NULL, 'r' },
205 { "busid", required_argument, NULL, 'b' }, 209 { "busid", required_argument, NULL, 'b' },
210 { "device", required_argument, NULL, 'd' },
206 { NULL, 0, NULL, 0 } 211 { NULL, 0, NULL, 0 }
207 }; 212 };
208 char *host = NULL; 213 char *host = NULL;
@@ -211,7 +216,7 @@ int usbip_attach(int argc, char *argv[])
211 int ret = -1; 216 int ret = -1;
212 217
213 for (;;) { 218 for (;;) {
214 opt = getopt_long(argc, argv, "r:b:", opts, NULL); 219 opt = getopt_long(argc, argv, "d:r:b:", opts, NULL);
215 220
216 if (opt == -1) 221 if (opt == -1)
217 break; 222 break;
@@ -220,6 +225,7 @@ int usbip_attach(int argc, char *argv[])
220 case 'r': 225 case 'r':
221 host = optarg; 226 host = optarg;
222 break; 227 break;
228 case 'd':
223 case 'b': 229 case 'b':
224 busid = optarg; 230 busid = optarg;
225 break; 231 break;
diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c
index d5ce34a410e7..f1b38e866dd7 100644
--- a/tools/usb/usbip/src/usbip_list.c
+++ b/tools/usb/usbip/src/usbip_list.c
@@ -1,6 +1,9 @@
1/* 1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi 3 * 2005-2007 Takahiro Hirofuchi
4 * Copyright (C) 2015-2016 Samsung Electronics
5 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
6 * Krzysztof Opasiak <k.opasiak@samsung.com>
4 * 7 *
5 * This program is free software: you can redistribute it and/or modify 8 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
@@ -30,6 +33,10 @@
30#include <netdb.h> 33#include <netdb.h>
31#include <unistd.h> 34#include <unistd.h>
32 35
36#include <dirent.h>
37
38#include <linux/usb/ch9.h>
39
33#include "usbip_common.h" 40#include "usbip_common.h"
34#include "usbip_network.h" 41#include "usbip_network.h"
35#include "usbip.h" 42#include "usbip.h"
@@ -205,8 +212,10 @@ static int list_devices(bool parsable)
205 /* Get device information. */ 212 /* Get device information. */
206 idVendor = udev_device_get_sysattr_value(dev, "idVendor"); 213 idVendor = udev_device_get_sysattr_value(dev, "idVendor");
207 idProduct = udev_device_get_sysattr_value(dev, "idProduct"); 214 idProduct = udev_device_get_sysattr_value(dev, "idProduct");
208 bConfValue = udev_device_get_sysattr_value(dev, "bConfigurationValue"); 215 bConfValue = udev_device_get_sysattr_value(dev,
209 bNumIntfs = udev_device_get_sysattr_value(dev, "bNumInterfaces"); 216 "bConfigurationValue");
217 bNumIntfs = udev_device_get_sysattr_value(dev,
218 "bNumInterfaces");
210 busid = udev_device_get_sysname(dev); 219 busid = udev_device_get_sysname(dev);
211 if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) { 220 if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) {
212 err("problem getting device attributes: %s", 221 err("problem getting device attributes: %s",
@@ -237,12 +246,90 @@ err_out:
237 return ret; 246 return ret;
238} 247}
239 248
249static int list_gadget_devices(bool parsable)
250{
251 int ret = -1;
252 struct udev *udev;
253 struct udev_enumerate *enumerate;
254 struct udev_list_entry *devices, *dev_list_entry;
255 struct udev_device *dev;
256 const char *path;
257 const char *driver;
258
259 const struct usb_device_descriptor *d_desc;
260 const char *descriptors;
261 char product_name[128];
262
263 uint16_t idVendor;
264 char idVendor_buf[8];
265 uint16_t idProduct;
266 char idProduct_buf[8];
267 const char *busid;
268
269 udev = udev_new();
270 enumerate = udev_enumerate_new(udev);
271
272 udev_enumerate_add_match_subsystem(enumerate, "platform");
273
274 udev_enumerate_scan_devices(enumerate);
275 devices = udev_enumerate_get_list_entry(enumerate);
276
277 udev_list_entry_foreach(dev_list_entry, devices) {
278 path = udev_list_entry_get_name(dev_list_entry);
279 dev = udev_device_new_from_syspath(udev, path);
280
281 driver = udev_device_get_driver(dev);
282 /* We only have mechanism to enumerate gadgets bound to vudc */
283 if (driver == NULL || strcmp(driver, USBIP_DEVICE_DRV_NAME))
284 continue;
285
286 /* Get device information. */
287 descriptors = udev_device_get_sysattr_value(dev,
288 VUDC_DEVICE_DESCR_FILE);
289
290 if (!descriptors) {
291 err("problem getting device attributes: %s",
292 strerror(errno));
293 goto err_out;
294 }
295
296 d_desc = (const struct usb_device_descriptor *) descriptors;
297
298 idVendor = le16toh(d_desc->idVendor);
299 sprintf(idVendor_buf, "0x%4x", idVendor);
300 idProduct = le16toh(d_desc->idProduct);
301 sprintf(idProduct_buf, "0x%4x", idVendor);
302 busid = udev_device_get_sysname(dev);
303
304 /* Get product name. */
305 usbip_names_get_product(product_name, sizeof(product_name),
306 le16toh(idVendor),
307 le16toh(idProduct));
308
309 /* Print information. */
310 print_device(busid, idVendor_buf, idProduct_buf, parsable);
311 print_product_name(product_name, parsable);
312
313 printf("\n");
314
315 udev_device_unref(dev);
316 }
317 ret = 0;
318
319err_out:
320 udev_enumerate_unref(enumerate);
321 udev_unref(udev);
322
323 return ret;
324}
325
240int usbip_list(int argc, char *argv[]) 326int usbip_list(int argc, char *argv[])
241{ 327{
242 static const struct option opts[] = { 328 static const struct option opts[] = {
243 { "parsable", no_argument, NULL, 'p' }, 329 { "parsable", no_argument, NULL, 'p' },
244 { "remote", required_argument, NULL, 'r' }, 330 { "remote", required_argument, NULL, 'r' },
245 { "local", no_argument, NULL, 'l' }, 331 { "local", no_argument, NULL, 'l' },
332 { "device", no_argument, NULL, 'd' },
246 { NULL, 0, NULL, 0 } 333 { NULL, 0, NULL, 0 }
247 }; 334 };
248 335
@@ -254,7 +341,7 @@ int usbip_list(int argc, char *argv[])
254 err("failed to open %s", USBIDS_FILE); 341 err("failed to open %s", USBIDS_FILE);
255 342
256 for (;;) { 343 for (;;) {
257 opt = getopt_long(argc, argv, "pr:l", opts, NULL); 344 opt = getopt_long(argc, argv, "pr:ld", opts, NULL);
258 345
259 if (opt == -1) 346 if (opt == -1)
260 break; 347 break;
@@ -269,6 +356,9 @@ int usbip_list(int argc, char *argv[])
269 case 'l': 356 case 'l':
270 ret = list_devices(parsable); 357 ret = list_devices(parsable);
271 goto out; 358 goto out;
359 case 'd':
360 ret = list_gadget_devices(parsable);
361 goto out;
272 default: 362 default:
273 goto err_out; 363 goto err_out;
274 } 364 }
diff --git a/tools/usb/usbip/src/usbip_port.c b/tools/usb/usbip/src/usbip_port.c
index a2e884fd9226..7bd74fb3a9cd 100644
--- a/tools/usb/usbip/src/usbip_port.c
+++ b/tools/usb/usbip/src/usbip_port.c
@@ -22,10 +22,13 @@ static int list_imported_devices(void)
22 struct usbip_imported_device *idev; 22 struct usbip_imported_device *idev;
23 int ret; 23 int ret;
24 24
25 if (usbip_names_init(USBIDS_FILE))
26 err("failed to open %s", USBIDS_FILE);
27
25 ret = usbip_vhci_driver_open(); 28 ret = usbip_vhci_driver_open();
26 if (ret < 0) { 29 if (ret < 0) {
27 err("open vhci_driver"); 30 err("open vhci_driver");
28 return -1; 31 goto err_names_free;
29 } 32 }
30 33
31 printf("Imported USB devices\n"); 34 printf("Imported USB devices\n");
@@ -35,13 +38,19 @@ static int list_imported_devices(void)
35 idev = &vhci_driver->idev[i]; 38 idev = &vhci_driver->idev[i];
36 39
37 if (usbip_vhci_imported_device_dump(idev) < 0) 40 if (usbip_vhci_imported_device_dump(idev) < 0)
38 ret = -1; 41 goto err_driver_close;
39 } 42 }
40 43
41 usbip_vhci_driver_close(); 44 usbip_vhci_driver_close();
45 usbip_names_free();
42 46
43 return ret; 47 return ret;
44 48
49err_driver_close:
50 usbip_vhci_driver_close();
51err_names_free:
52 usbip_names_free();
53 return -1;
45} 54}
46 55
47int usbip_port_show(__attribute__((unused)) int argc, 56int usbip_port_show(__attribute__((unused)) int argc,
diff --git a/tools/usb/usbip/src/usbipd.c b/tools/usb/usbip/src/usbipd.c
index 2a7cd2b8d966..a0972dea9e6c 100644
--- a/tools/usb/usbip/src/usbipd.c
+++ b/tools/usb/usbip/src/usbipd.c
@@ -1,6 +1,9 @@
1/* 1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi 3 * 2005-2007 Takahiro Hirofuchi
4 * Copyright (C) 2015-2016 Samsung Electronics
5 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
6 * Krzysztof Opasiak <k.opasiak@samsung.com>
4 * 7 *
5 * This program is free software: you can redistribute it and/or modify 8 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
@@ -41,6 +44,8 @@
41#include <poll.h> 44#include <poll.h>
42 45
43#include "usbip_host_driver.h" 46#include "usbip_host_driver.h"
47#include "usbip_host_common.h"
48#include "usbip_device_driver.h"
44#include "usbip_common.h" 49#include "usbip_common.h"
45#include "usbip_network.h" 50#include "usbip_network.h"
46#include "list.h" 51#include "list.h"
@@ -64,6 +69,11 @@ static const char usbipd_help_string[] =
64 " -6, --ipv6\n" 69 " -6, --ipv6\n"
65 " Bind to IPv6. Default is both.\n" 70 " Bind to IPv6. Default is both.\n"
66 "\n" 71 "\n"
72 " -e, --device\n"
73 " Run in device mode.\n"
74 " Rather than drive an attached device, create\n"
75 " a virtual UDC to bind gadgets to.\n"
76 "\n"
67 " -D, --daemon\n" 77 " -D, --daemon\n"
68 " Run as a daemon process.\n" 78 " Run as a daemon process.\n"
69 "\n" 79 "\n"
@@ -83,6 +93,8 @@ static const char usbipd_help_string[] =
83 " -v, --version\n" 93 " -v, --version\n"
84 " Show version.\n"; 94 " Show version.\n";
85 95
96static struct usbip_host_driver *driver;
97
86static void usbipd_help(void) 98static void usbipd_help(void)
87{ 99{
88 printf("%s\n", usbipd_help_string); 100 printf("%s\n", usbipd_help_string);
@@ -107,7 +119,7 @@ static int recv_request_import(int sockfd)
107 } 119 }
108 PACK_OP_IMPORT_REQUEST(0, &req); 120 PACK_OP_IMPORT_REQUEST(0, &req);
109 121
110 list_for_each(i, &host_driver->edev_list) { 122 list_for_each(i, &driver->edev_list) {
111 edev = list_entry(i, struct usbip_exported_device, node); 123 edev = list_entry(i, struct usbip_exported_device, node);
112 if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) { 124 if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) {
113 info("found requested device: %s", req.busid); 125 info("found requested device: %s", req.busid);
@@ -121,7 +133,7 @@ static int recv_request_import(int sockfd)
121 usbip_net_set_nodelay(sockfd); 133 usbip_net_set_nodelay(sockfd);
122 134
123 /* export device needs a TCP/IP socket descriptor */ 135 /* export device needs a TCP/IP socket descriptor */
124 rc = usbip_host_export_device(edev, sockfd); 136 rc = usbip_export_device(edev, sockfd);
125 if (rc < 0) 137 if (rc < 0)
126 error = 1; 138 error = 1;
127 } else { 139 } else {
@@ -166,7 +178,7 @@ static int send_reply_devlist(int connfd)
166 178
167 reply.ndev = 0; 179 reply.ndev = 0;
168 /* number of exported devices */ 180 /* number of exported devices */
169 list_for_each(j, &host_driver->edev_list) { 181 list_for_each(j, &driver->edev_list) {
170 reply.ndev += 1; 182 reply.ndev += 1;
171 } 183 }
172 info("exportable devices: %d", reply.ndev); 184 info("exportable devices: %d", reply.ndev);
@@ -184,7 +196,7 @@ static int send_reply_devlist(int connfd)
184 return -1; 196 return -1;
185 } 197 }
186 198
187 list_for_each(j, &host_driver->edev_list) { 199 list_for_each(j, &driver->edev_list) {
188 edev = list_entry(j, struct usbip_exported_device, node); 200 edev = list_entry(j, struct usbip_exported_device, node);
189 dump_usb_device(&edev->udev); 201 dump_usb_device(&edev->udev);
190 memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); 202 memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));
@@ -246,7 +258,7 @@ static int recv_pdu(int connfd)
246 return -1; 258 return -1;
247 } 259 }
248 260
249 ret = usbip_host_refresh_device_list(); 261 ret = usbip_refresh_device_list(driver);
250 if (ret < 0) { 262 if (ret < 0) {
251 dbg("could not refresh device list: %d", ret); 263 dbg("could not refresh device list: %d", ret);
252 return -1; 264 return -1;
@@ -491,16 +503,13 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6)
491 struct timespec timeout; 503 struct timespec timeout;
492 sigset_t sigmask; 504 sigset_t sigmask;
493 505
494 if (usbip_host_driver_open()) { 506 if (usbip_driver_open(driver))
495 err("please load " USBIP_CORE_MOD_NAME ".ko and "
496 USBIP_HOST_DRV_NAME ".ko!");
497 return -1; 507 return -1;
498 }
499 508
500 if (daemonize) { 509 if (daemonize) {
501 if (daemon(0, 0) < 0) { 510 if (daemon(0, 0) < 0) {
502 err("daemonizing failed: %s", strerror(errno)); 511 err("daemonizing failed: %s", strerror(errno));
503 usbip_host_driver_close(); 512 usbip_driver_close(driver);
504 return -1; 513 return -1;
505 } 514 }
506 umask(0); 515 umask(0);
@@ -525,7 +534,7 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6)
525 534
526 ai_head = do_getaddrinfo(NULL, family); 535 ai_head = do_getaddrinfo(NULL, family);
527 if (!ai_head) { 536 if (!ai_head) {
528 usbip_host_driver_close(); 537 usbip_driver_close(driver);
529 return -1; 538 return -1;
530 } 539 }
531 nsockfd = listen_all_addrinfo(ai_head, sockfdlist, 540 nsockfd = listen_all_addrinfo(ai_head, sockfdlist,
@@ -533,7 +542,7 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6)
533 freeaddrinfo(ai_head); 542 freeaddrinfo(ai_head);
534 if (nsockfd <= 0) { 543 if (nsockfd <= 0) {
535 err("failed to open a listening socket"); 544 err("failed to open a listening socket");
536 usbip_host_driver_close(); 545 usbip_driver_close(driver);
537 return -1; 546 return -1;
538 } 547 }
539 548
@@ -574,7 +583,7 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6)
574 583
575 info("shutting down " PROGNAME); 584 info("shutting down " PROGNAME);
576 free(fds); 585 free(fds);
577 usbip_host_driver_close(); 586 usbip_driver_close(driver);
578 587
579 return 0; 588 return 0;
580} 589}
@@ -587,6 +596,7 @@ int main(int argc, char *argv[])
587 { "daemon", no_argument, NULL, 'D' }, 596 { "daemon", no_argument, NULL, 'D' },
588 { "daemon", no_argument, NULL, 'D' }, 597 { "daemon", no_argument, NULL, 'D' },
589 { "debug", no_argument, NULL, 'd' }, 598 { "debug", no_argument, NULL, 'd' },
599 { "device", no_argument, NULL, 'e' },
590 { "pid", optional_argument, NULL, 'P' }, 600 { "pid", optional_argument, NULL, 'P' },
591 { "tcp-port", required_argument, NULL, 't' }, 601 { "tcp-port", required_argument, NULL, 't' },
592 { "help", no_argument, NULL, 'h' }, 602 { "help", no_argument, NULL, 'h' },
@@ -613,8 +623,9 @@ int main(int argc, char *argv[])
613 err("not running as root?"); 623 err("not running as root?");
614 624
615 cmd = cmd_standalone_mode; 625 cmd = cmd_standalone_mode;
626 driver = &host_driver;
616 for (;;) { 627 for (;;) {
617 opt = getopt_long(argc, argv, "46DdP::t:hv", longopts, NULL); 628 opt = getopt_long(argc, argv, "46DdeP::t:hv", longopts, NULL);
618 629
619 if (opt == -1) 630 if (opt == -1)
620 break; 631 break;
@@ -644,6 +655,9 @@ int main(int argc, char *argv[])
644 case 'v': 655 case 'v':
645 cmd = cmd_version; 656 cmd = cmd_version;
646 break; 657 break;
658 case 'e':
659 driver = &device_driver;
660 break;
647 case '?': 661 case '?':
648 usbipd_help(); 662 usbipd_help();
649 default: 663 default:
diff --git a/tools/virtio/ringtest/Makefile b/tools/virtio/ringtest/Makefile
index feaa64ac4630..6ba745529833 100644
--- a/tools/virtio/ringtest/Makefile
+++ b/tools/virtio/ringtest/Makefile
@@ -1,6 +1,6 @@
1all: 1all:
2 2
3all: ring virtio_ring_0_9 virtio_ring_poll 3all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder
4 4
5CFLAGS += -Wall 5CFLAGS += -Wall
6CFLAGS += -pthread -O2 -ggdb 6CFLAGS += -pthread -O2 -ggdb
@@ -10,13 +10,16 @@ main.o: main.c main.h
10ring.o: ring.c main.h 10ring.o: ring.c main.h
11virtio_ring_0_9.o: virtio_ring_0_9.c main.h 11virtio_ring_0_9.o: virtio_ring_0_9.c main.h
12virtio_ring_poll.o: virtio_ring_poll.c virtio_ring_0_9.c main.h 12virtio_ring_poll.o: virtio_ring_poll.c virtio_ring_0_9.c main.h
13virtio_ring_inorder.o: virtio_ring_inorder.c virtio_ring_0_9.c main.h
13ring: ring.o main.o 14ring: ring.o main.o
14virtio_ring_0_9: virtio_ring_0_9.o main.o 15virtio_ring_0_9: virtio_ring_0_9.o main.o
15virtio_ring_poll: virtio_ring_poll.o main.o 16virtio_ring_poll: virtio_ring_poll.o main.o
17virtio_ring_inorder: virtio_ring_inorder.o main.o
16clean: 18clean:
17 -rm main.o 19 -rm main.o
18 -rm ring.o ring 20 -rm ring.o ring
19 -rm virtio_ring_0_9.o virtio_ring_0_9 21 -rm virtio_ring_0_9.o virtio_ring_0_9
20 -rm virtio_ring_poll.o virtio_ring_poll 22 -rm virtio_ring_poll.o virtio_ring_poll
23 -rm virtio_ring_inorder.o virtio_ring_inorder
21 24
22.PHONY: all clean 25.PHONY: all clean
diff --git a/tools/virtio/ringtest/main.c b/tools/virtio/ringtest/main.c
index 3a5ff438bd62..147abb452a6c 100644
--- a/tools/virtio/ringtest/main.c
+++ b/tools/virtio/ringtest/main.c
@@ -115,7 +115,7 @@ static void run_guest(void)
115 do { 115 do {
116 if (started < bufs && 116 if (started < bufs &&
117 started - completed < max_outstanding) { 117 started - completed < max_outstanding) {
118 r = add_inbuf(0, NULL, "Hello, world!"); 118 r = add_inbuf(0, "Buffer\n", "Hello, world!");
119 if (__builtin_expect(r == 0, true)) { 119 if (__builtin_expect(r == 0, true)) {
120 ++started; 120 ++started;
121 if (!--tokick) { 121 if (!--tokick) {
diff --git a/tools/virtio/ringtest/virtio_ring_0_9.c b/tools/virtio/ringtest/virtio_ring_0_9.c
index 47c9a1a18d36..761866212aac 100644
--- a/tools/virtio/ringtest/virtio_ring_0_9.c
+++ b/tools/virtio/ringtest/virtio_ring_0_9.c
@@ -26,6 +26,14 @@ struct vring ring;
26 * high bits of ring id ^ 0x8000). 26 * high bits of ring id ^ 0x8000).
27 */ 27 */
28/* #ifdef RING_POLL */ 28/* #ifdef RING_POLL */
29/* enabling the below activates experimental in-order code
30 * (which skips ring updates and reads and writes len in descriptor).
31 */
32/* #ifdef INORDER */
33
34#if defined(RING_POLL) && defined(INORDER)
35#error "RING_POLL and INORDER are mutually exclusive"
36#endif
29 37
30/* how much padding is needed to avoid false cache sharing */ 38/* how much padding is needed to avoid false cache sharing */
31#define HOST_GUEST_PADDING 0x80 39#define HOST_GUEST_PADDING 0x80
@@ -35,7 +43,11 @@ struct guest {
35 unsigned short last_used_idx; 43 unsigned short last_used_idx;
36 unsigned short num_free; 44 unsigned short num_free;
37 unsigned short kicked_avail_idx; 45 unsigned short kicked_avail_idx;
46#ifndef INORDER
38 unsigned short free_head; 47 unsigned short free_head;
48#else
49 unsigned short reserved_free_head;
50#endif
39 unsigned char reserved[HOST_GUEST_PADDING - 10]; 51 unsigned char reserved[HOST_GUEST_PADDING - 10];
40} guest; 52} guest;
41 53
@@ -66,8 +78,10 @@ void alloc_ring(void)
66 guest.avail_idx = 0; 78 guest.avail_idx = 0;
67 guest.kicked_avail_idx = -1; 79 guest.kicked_avail_idx = -1;
68 guest.last_used_idx = 0; 80 guest.last_used_idx = 0;
81#ifndef INORDER
69 /* Put everything in free lists. */ 82 /* Put everything in free lists. */
70 guest.free_head = 0; 83 guest.free_head = 0;
84#endif
71 for (i = 0; i < ring_size - 1; i++) 85 for (i = 0; i < ring_size - 1; i++)
72 ring.desc[i].next = i + 1; 86 ring.desc[i].next = i + 1;
73 host.used_idx = 0; 87 host.used_idx = 0;
@@ -84,13 +98,20 @@ void alloc_ring(void)
84/* guest side */ 98/* guest side */
85int add_inbuf(unsigned len, void *buf, void *datap) 99int add_inbuf(unsigned len, void *buf, void *datap)
86{ 100{
87 unsigned head, avail; 101 unsigned head;
102#ifndef INORDER
103 unsigned avail;
104#endif
88 struct vring_desc *desc; 105 struct vring_desc *desc;
89 106
90 if (!guest.num_free) 107 if (!guest.num_free)
91 return -1; 108 return -1;
92 109
110#ifdef INORDER
111 head = (ring_size - 1) & (guest.avail_idx++);
112#else
93 head = guest.free_head; 113 head = guest.free_head;
114#endif
94 guest.num_free--; 115 guest.num_free--;
95 116
96 desc = ring.desc; 117 desc = ring.desc;
@@ -102,7 +123,9 @@ int add_inbuf(unsigned len, void *buf, void *datap)
102 * descriptors. 123 * descriptors.
103 */ 124 */
104 desc[head].flags &= ~VRING_DESC_F_NEXT; 125 desc[head].flags &= ~VRING_DESC_F_NEXT;
126#ifndef INORDER
105 guest.free_head = desc[head].next; 127 guest.free_head = desc[head].next;
128#endif
106 129
107 data[head].data = datap; 130 data[head].data = datap;
108 131
@@ -113,8 +136,12 @@ int add_inbuf(unsigned len, void *buf, void *datap)
113 ring.avail->ring[avail & (ring_size - 1)] = 136 ring.avail->ring[avail & (ring_size - 1)] =
114 (head | (avail & ~(ring_size - 1))) ^ 0x8000; 137 (head | (avail & ~(ring_size - 1))) ^ 0x8000;
115#else 138#else
139#ifndef INORDER
140 /* Barrier A (for pairing) */
141 smp_release();
116 avail = (ring_size - 1) & (guest.avail_idx++); 142 avail = (ring_size - 1) & (guest.avail_idx++);
117 ring.avail->ring[avail] = head; 143 ring.avail->ring[avail] = head;
144#endif
118 /* Barrier A (for pairing) */ 145 /* Barrier A (for pairing) */
119 smp_release(); 146 smp_release();
120#endif 147#endif
@@ -141,15 +168,27 @@ void *get_buf(unsigned *lenp, void **bufp)
141 return NULL; 168 return NULL;
142 /* Barrier B (for pairing) */ 169 /* Barrier B (for pairing) */
143 smp_acquire(); 170 smp_acquire();
171#ifdef INORDER
172 head = (ring_size - 1) & guest.last_used_idx;
173 index = head;
174#else
144 head = (ring_size - 1) & guest.last_used_idx; 175 head = (ring_size - 1) & guest.last_used_idx;
145 index = ring.used->ring[head].id; 176 index = ring.used->ring[head].id;
146#endif 177#endif
178
179#endif
180#ifdef INORDER
181 *lenp = ring.desc[index].len;
182#else
147 *lenp = ring.used->ring[head].len; 183 *lenp = ring.used->ring[head].len;
184#endif
148 datap = data[index].data; 185 datap = data[index].data;
149 *bufp = (void*)(unsigned long)ring.desc[index].addr; 186 *bufp = (void*)(unsigned long)ring.desc[index].addr;
150 data[index].data = NULL; 187 data[index].data = NULL;
188#ifndef INORDER
151 ring.desc[index].next = guest.free_head; 189 ring.desc[index].next = guest.free_head;
152 guest.free_head = index; 190 guest.free_head = index;
191#endif
153 guest.num_free++; 192 guest.num_free++;
154 guest.last_used_idx++; 193 guest.last_used_idx++;
155 return datap; 194 return datap;
@@ -283,16 +322,24 @@ bool use_buf(unsigned *lenp, void **bufp)
283 smp_acquire(); 322 smp_acquire();
284 323
285 used_idx &= ring_size - 1; 324 used_idx &= ring_size - 1;
325#ifdef INORDER
326 head = used_idx;
327#else
286 head = ring.avail->ring[used_idx]; 328 head = ring.avail->ring[used_idx];
329#endif
287 desc = &ring.desc[head]; 330 desc = &ring.desc[head];
288#endif 331#endif
289 332
290 *lenp = desc->len; 333 *lenp = desc->len;
291 *bufp = (void *)(unsigned long)desc->addr; 334 *bufp = (void *)(unsigned long)desc->addr;
292 335
336#ifdef INORDER
337 desc->len = desc->len - 1;
338#else
293 /* now update used ring */ 339 /* now update used ring */
294 ring.used->ring[used_idx].id = head; 340 ring.used->ring[used_idx].id = head;
295 ring.used->ring[used_idx].len = desc->len - 1; 341 ring.used->ring[used_idx].len = desc->len - 1;
342#endif
296 /* Barrier B (for pairing) */ 343 /* Barrier B (for pairing) */
297 smp_release(); 344 smp_release();
298 host.used_idx++; 345 host.used_idx++;
diff --git a/tools/virtio/ringtest/virtio_ring_inorder.c b/tools/virtio/ringtest/virtio_ring_inorder.c
new file mode 100644
index 000000000000..2438ca58a2ad
--- /dev/null
+++ b/tools/virtio/ringtest/virtio_ring_inorder.c
@@ -0,0 +1,2 @@
1#define INORDER 1
2#include "virtio_ring_0_9.c"