aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile7
-rw-r--r--tools/build/Makefile2
-rw-r--r--tools/gpio/Makefile2
-rw-r--r--tools/gpio/gpio-hammer.c67
-rw-r--r--tools/gpio/gpio-utils.c256
-rw-r--r--tools/gpio/gpio-utils.h16
-rw-r--r--tools/hv/Makefile3
-rw-r--r--tools/hv/hv_fcopy_daemon.c7
-rw-r--r--tools/hv/hv_kvp_daemon.c20
-rw-r--r--tools/iio/iio_generic_buffer.c18
-rw-r--r--tools/include/asm/bug.h11
-rw-r--r--tools/include/linux/bitmap.h26
-rw-r--r--tools/include/linux/types.h4
-rw-r--r--tools/include/uapi/linux/hw_breakpoint.h4
-rw-r--r--tools/leds/.gitignore1
-rw-r--r--tools/leds/Makefile13
-rw-r--r--tools/leds/uledmon.c63
-rw-r--r--tools/lib/api/Makefile2
-rw-r--r--tools/lib/bpf/Makefile2
-rw-r--r--tools/lib/lockdep/Makefile2
-rw-r--r--tools/lib/subcmd/Makefile2
-rw-r--r--tools/lib/traceevent/Makefile2
-rw-r--r--tools/objtool/Makefile4
-rw-r--r--tools/perf/Makefile.perf2
-rw-r--r--tools/perf/tests/make2
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixxf.c13
-rw-r--r--tools/power/acpi/tools/ec/ec_access.c2
-rw-r--r--tools/power/cpupower/Makefile3
-rw-r--r--tools/power/cpupower/debug/kernel/Makefile3
-rw-r--r--tools/spi/spidev_test.c2
-rwxr-xr-xtools/testing/ktest/ktest.pl8
-rw-r--r--tools/testing/radix-tree/Makefile15
-rw-r--r--tools/testing/radix-tree/benchmark.c98
-rw-r--r--tools/testing/radix-tree/find_next_bit.c57
-rw-r--r--tools/testing/radix-tree/iteration_check.c123
-rw-r--r--tools/testing/radix-tree/linux.c67
-rw-r--r--tools/testing/radix-tree/linux/bitops.h40
-rw-r--r--tools/testing/radix-tree/linux/bitops/non-atomic.h13
-rw-r--r--tools/testing/radix-tree/linux/bug.h2
-rw-r--r--tools/testing/radix-tree/linux/cpu.h22
-rw-r--r--tools/testing/radix-tree/linux/gfp.h22
-rw-r--r--tools/testing/radix-tree/linux/kernel.h18
-rw-r--r--tools/testing/radix-tree/linux/notifier.h8
-rw-r--r--tools/testing/radix-tree/linux/preempt.h6
-rw-r--r--tools/testing/radix-tree/linux/slab.h11
-rw-r--r--tools/testing/radix-tree/linux/types.h2
-rw-r--r--tools/testing/radix-tree/main.c77
-rw-r--r--tools/testing/radix-tree/multiorder.c328
-rw-r--r--tools/testing/radix-tree/rcupdate.c86
-rw-r--r--tools/testing/radix-tree/regression2.c3
-rw-r--r--tools/testing/radix-tree/regression3.c8
-rw-r--r--tools/testing/radix-tree/tag_check.c12
-rw-r--r--tools/testing/radix-tree/test.c92
-rw-r--r--tools/testing/radix-tree/test.h21
-rw-r--r--tools/testing/selftests/.gitignore1
-rw-r--r--tools/testing/selftests/Makefile2
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c30
-rw-r--r--tools/testing/selftests/breakpoints/Makefile5
-rw-r--r--tools/testing/selftests/breakpoints/breakpoint_test_arm64.c236
-rwxr-xr-xtools/testing/selftests/drivers/gpu/i915.sh14
-rw-r--r--tools/testing/selftests/ftrace/.gitignore1
-rwxr-xr-xtools/testing/selftests/ftrace/ftracetest16
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc49
-rw-r--r--tools/testing/selftests/ftrace/test.d/functions28
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_type.tc37
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc2
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc5
-rw-r--r--tools/testing/selftests/futex/README2
-rw-r--r--tools/testing/selftests/gpio/Makefile23
-rw-r--r--tools/testing/selftests/gpio/gpio-mockup-chardev.c324
-rwxr-xr-xtools/testing/selftests/gpio/gpio-mockup-sysfs.sh134
-rwxr-xr-xtools/testing/selftests/gpio/gpio-mockup.sh201
-rw-r--r--tools/testing/selftests/nsfs/.gitignore2
-rw-r--r--tools/testing/selftests/powerpc/Makefile5
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/.gitignore3
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/Makefile2
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/context_switch.c2
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/null_syscall.c157
-rw-r--r--tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h2
-rw-r--r--tools/testing/selftests/powerpc/copyloops/validate.c2
-rw-r--r--tools/testing/selftests/powerpc/dscr/dscr.h10
-rw-r--r--tools/testing/selftests/powerpc/include/basic_asm.h (renamed from tools/testing/selftests/powerpc/basic_asm.h)37
-rw-r--r--tools/testing/selftests/powerpc/include/fpu_asm.h (renamed from tools/testing/selftests/powerpc/fpu_asm.h)0
-rw-r--r--tools/testing/selftests/powerpc/include/gpr_asm.h (renamed from tools/testing/selftests/powerpc/gpr_asm.h)0
-rw-r--r--tools/testing/selftests/powerpc/include/instructions.h (renamed from tools/testing/selftests/powerpc/instructions.h)0
-rw-r--r--tools/testing/selftests/powerpc/include/reg.h145
-rw-r--r--tools/testing/selftests/powerpc/include/subunit.h (renamed from tools/testing/selftests/powerpc/subunit.h)0
-rw-r--r--tools/testing/selftests/powerpc/include/utils.h (renamed from tools/testing/selftests/powerpc/utils.h)0
-rw-r--r--tools/testing/selftests/powerpc/include/vmx_asm.h (renamed from tools/testing/selftests/powerpc/vmx_asm.h)0
-rw-r--r--tools/testing/selftests/powerpc/include/vsx_asm.h (renamed from tools/testing/selftests/powerpc/vsx_asm.h)0
-rw-r--r--tools/testing/selftests/powerpc/lib/reg.S397
-rw-r--r--tools/testing/selftests/powerpc/math/fpu_asm.S4
-rw-r--r--tools/testing/selftests/powerpc/math/vmx_asm.S4
-rw-r--r--tools/testing/selftests/powerpc/math/vsx_asm.S4
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/.gitignore2
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/Makefile2
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.c143
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.h39
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr_regs.c37
-rw-r--r--tools/testing/selftests/powerpc/pmu/lib.c6
-rw-r--r--tools/testing/selftests/powerpc/primitives/asm/firmware.h0
l---------tools/testing/selftests/powerpc/primitives/asm/ppc_asm.h1
-rw-r--r--tools/testing/selftests/powerpc/primitives/asm/processor.h0
-rw-r--r--tools/testing/selftests/powerpc/primitives/linux/stringify.h0
-rw-r--r--tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c21
-rw-r--r--tools/testing/selftests/powerpc/ptrace/.gitignore10
-rw-r--r--tools/testing/selftests/powerpc/ptrace/Makefile14
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-gpr.c123
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-gpr.h74
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tar.c135
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tar.h50
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tm-gpr.c158
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c169
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-tar.c174
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c185
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c168
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tm-tar.c160
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c168
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-vsx.c117
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-vsx.h127
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace.h711
-rw-r--r--tools/testing/selftests/powerpc/reg.h60
-rw-r--r--tools/testing/selftests/powerpc/signal/signal.S2
-rw-r--r--tools/testing/selftests/powerpc/stringloops/memcmp.c2
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal.S10
-rw-r--r--tools/testing/selftests/powerpc/tm/tm.h2
-rw-r--r--tools/testing/selftests/sigaltstack/.gitignore1
-rw-r--r--tools/testing/selftests/sync/.gitignore1
-rw-r--r--tools/testing/selftests/sync/Makefile24
-rw-r--r--tools/testing/selftests/sync/sw_sync.h46
-rw-r--r--tools/testing/selftests/sync/sync.c221
-rw-r--r--tools/testing/selftests/sync/sync.h40
-rw-r--r--tools/testing/selftests/sync/sync_alloc.c74
-rw-r--r--tools/testing/selftests/sync/sync_fence.c132
-rw-r--r--tools/testing/selftests/sync/sync_merge.c60
-rw-r--r--tools/testing/selftests/sync/sync_stress_consumer.c185
-rw-r--r--tools/testing/selftests/sync/sync_stress_merge.c115
-rw-r--r--tools/testing/selftests/sync/sync_stress_parallelism.c111
-rw-r--r--tools/testing/selftests/sync/sync_test.c79
-rw-r--r--tools/testing/selftests/sync/sync_wait.c91
-rw-r--r--tools/testing/selftests/sync/synctest.h66
-rw-r--r--tools/testing/selftests/timers/.gitignore1
-rw-r--r--tools/usb/usbip/.gitignore4
-rw-r--r--tools/usb/usbip/src/usbipd.c7
-rw-r--r--tools/virtio/linux/compiler.h2
-rw-r--r--tools/virtio/linux/uaccess.h9
146 files changed, 6932 insertions, 793 deletions
diff --git a/tools/Makefile b/tools/Makefile
index daa8fb3e4363..00caacd3ed92 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -17,6 +17,7 @@ help:
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 ' kvm_stat - top-like utility for displaying kvm statistics'
20 @echo ' leds - LEDs tools'
20 @echo ' lguest - a minimal 32-bit x86 hypervisor' 21 @echo ' lguest - a minimal 32-bit x86 hypervisor'
21 @echo ' net - misc networking tools' 22 @echo ' net - misc networking tools'
22 @echo ' perf - Linux performance measurement and analysis tool' 23 @echo ' perf - Linux performance measurement and analysis tool'
@@ -56,7 +57,7 @@ acpi: FORCE
56cpupower: FORCE 57cpupower: FORCE
57 $(call descend,power/$@) 58 $(call descend,power/$@)
58 59
59cgroup firewire hv guest spi usb virtio vm net iio gpio objtool: FORCE 60cgroup firewire hv guest spi usb virtio vm net iio gpio objtool leds: FORCE
60 $(call descend,$@) 61 $(call descend,$@)
61 62
62liblockdep: FORCE 63liblockdep: FORCE
@@ -126,7 +127,7 @@ acpi_clean:
126cpupower_clean: 127cpupower_clean:
127 $(call descend,power/cpupower,clean) 128 $(call descend,power/cpupower,clean)
128 129
129cgroup_clean hv_clean firewire_clean lguest_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean gpio_clean objtool_clean: 130cgroup_clean hv_clean firewire_clean lguest_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean gpio_clean objtool_clean leds_clean:
130 $(call descend,$(@:_clean=),clean) 131 $(call descend,$(@:_clean=),clean)
131 132
132liblockdep_clean: 133liblockdep_clean:
@@ -164,6 +165,6 @@ clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean lguest_cle
164 perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \ 165 perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \
165 vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ 166 vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
166 freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \ 167 freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \
167 gpio_clean objtool_clean 168 gpio_clean objtool_clean leds_clean
168 169
169.PHONY: FORCE 170.PHONY: FORCE
diff --git a/tools/build/Makefile b/tools/build/Makefile
index 8332959fbca4..aaf7ed329a45 100644
--- a/tools/build/Makefile
+++ b/tools/build/Makefile
@@ -1,5 +1,5 @@
1ifeq ($(srctree),) 1ifeq ($(srctree),)
2srctree := $(patsubst %/,%,$(dir $(shell pwd))) 2srctree := $(patsubst %/,%,$(dir $(CURDIR)))
3srctree := $(patsubst %/,%,$(dir $(srctree))) 3srctree := $(patsubst %/,%,$(dir $(srctree)))
4endif 4endif
5 5
diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile
index 250a891e6ef0..b4401536cfa9 100644
--- a/tools/gpio/Makefile
+++ b/tools/gpio/Makefile
@@ -3,7 +3,7 @@ include ../scripts/Makefile.include
3bindir ?= /usr/bin 3bindir ?= /usr/bin
4 4
5ifeq ($(srctree),) 5ifeq ($(srctree),)
6srctree := $(patsubst %/,%,$(dir $(shell pwd))) 6srctree := $(patsubst %/,%,$(dir $(CURDIR)))
7srctree := $(patsubst %/,%,$(dir $(srctree))) 7srctree := $(patsubst %/,%,$(dir $(srctree)))
8endif 8endif
9 9
diff --git a/tools/gpio/gpio-hammer.c b/tools/gpio/gpio-hammer.c
index 37b3f141053d..f1eab587dfea 100644
--- a/tools/gpio/gpio-hammer.c
+++ b/tools/gpio/gpio-hammer.c
@@ -23,54 +23,31 @@
23#include <getopt.h> 23#include <getopt.h>
24#include <sys/ioctl.h> 24#include <sys/ioctl.h>
25#include <linux/gpio.h> 25#include <linux/gpio.h>
26#include "gpio-utils.h"
26 27
27int hammer_device(const char *device_name, unsigned int *lines, int nlines, 28int hammer_device(const char *device_name, unsigned int *lines, int nlines,
28 unsigned int loops) 29 unsigned int loops)
29{ 30{
30 struct gpiohandle_request req;
31 struct gpiohandle_data data; 31 struct gpiohandle_data data;
32 char *chrdev_name;
33 char swirr[] = "-\\|/"; 32 char swirr[] = "-\\|/";
34 int fd; 33 int fd;
35 int ret; 34 int ret;
36 int i, j; 35 int i, j;
37 unsigned int iteration = 0; 36 unsigned int iteration = 0;
38 37
39 ret = asprintf(&chrdev_name, "/dev/%s", device_name); 38 memset(&data.values, 0, sizeof(data.values));
39 ret = gpiotools_request_linehandle(device_name, lines, nlines,
40 GPIOHANDLE_REQUEST_OUTPUT, &data,
41 "gpio-hammler");
40 if (ret < 0) 42 if (ret < 0)
41 return -ENOMEM; 43 goto exit_error;
44 else
45 fd = ret;
42 46
43 fd = open(chrdev_name, 0); 47 ret = gpiotools_get_values(fd, &data);
44 if (fd == -1) { 48 if (ret < 0)
45 ret = -errno;
46 fprintf(stderr, "Failed to open %s\n", chrdev_name);
47 goto exit_close_error;
48 }
49
50 /* Request lines as output */
51 for (i = 0; i < nlines; i++)
52 req.lineoffsets[i] = lines[i];
53 req.flags = GPIOHANDLE_REQUEST_OUTPUT; /* Request as output */
54 strcpy(req.consumer_label, "gpio-hammer");
55 req.lines = nlines;
56 ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
57 if (ret == -1) {
58 ret = -errno;
59 fprintf(stderr, "Failed to issue GET LINEHANDLE "
60 "IOCTL (%d)\n",
61 ret);
62 goto exit_close_error; 49 goto exit_close_error;
63 }
64 50
65 /* Read initial states */
66 ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
67 if (ret == -1) {
68 ret = -errno;
69 fprintf(stderr, "Failed to issue GPIOHANDLE GET LINE "
70 "VALUES IOCTL (%d)\n",
71 ret);
72 goto exit_close_error;
73 }
74 fprintf(stdout, "Hammer lines ["); 51 fprintf(stdout, "Hammer lines [");
75 for (i = 0; i < nlines; i++) { 52 for (i = 0; i < nlines; i++) {
76 fprintf(stdout, "%d", lines[i]); 53 fprintf(stdout, "%d", lines[i]);
@@ -92,23 +69,14 @@ int hammer_device(const char *device_name, unsigned int *lines, int nlines,
92 for (i = 0; i < nlines; i++) 69 for (i = 0; i < nlines; i++)
93 data.values[i] = !data.values[i]; 70 data.values[i] = !data.values[i];
94 71
95 ret = ioctl(req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data); 72 ret = gpiotools_set_values(fd, &data);
96 if (ret == -1) { 73 if (ret < 0)
97 ret = -errno;
98 fprintf(stderr, "Failed to issue GPIOHANDLE SET LINE "
99 "VALUES IOCTL (%d)\n",
100 ret);
101 goto exit_close_error; 74 goto exit_close_error;
102 } 75
103 /* Re-read values to get status */ 76 /* Re-read values to get status */
104 ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); 77 ret = gpiotools_get_values(fd, &data);
105 if (ret == -1) { 78 if (ret < 0)
106 ret = -errno;
107 fprintf(stderr, "Failed to issue GPIOHANDLE GET LINE "
108 "VALUES IOCTL (%d)\n",
109 ret);
110 goto exit_close_error; 79 goto exit_close_error;
111 }
112 80
113 fprintf(stdout, "[%c] ", swirr[j]); 81 fprintf(stdout, "[%c] ", swirr[j]);
114 j++; 82 j++;
@@ -132,9 +100,8 @@ int hammer_device(const char *device_name, unsigned int *lines, int nlines,
132 ret = 0; 100 ret = 0;
133 101
134exit_close_error: 102exit_close_error:
135 if (close(fd) == -1) 103 gpiotools_release_linehandle(fd);
136 perror("Failed to close GPIO character device file"); 104exit_error:
137 free(chrdev_name);
138 return ret; 105 return ret;
139} 106}
140 107
diff --git a/tools/gpio/gpio-utils.c b/tools/gpio/gpio-utils.c
index 8208718f2c99..b86a32d90d88 100644
--- a/tools/gpio/gpio-utils.c
+++ b/tools/gpio/gpio-utils.c
@@ -2,10 +2,266 @@
2 * GPIO tools - helpers library for the GPIO tools 2 * GPIO tools - helpers library for the GPIO tools
3 * 3 *
4 * Copyright (C) 2015 Linus Walleij 4 * Copyright (C) 2015 Linus Walleij
5 * Copyright (C) 2016 Bamvor Jian Zhang
5 * 6 *
6 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by 8 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation. 9 * the Free Software Foundation.
9 */ 10 */
10 11
12#include <unistd.h>
13#include <stdlib.h>
14#include <stdio.h>
15#include <errno.h>
16#include <string.h>
17#include <fcntl.h>
18#include <getopt.h>
19#include <sys/ioctl.h>
20#include <linux/gpio.h>
11#include "gpio-utils.h" 21#include "gpio-utils.h"
22
23#define COMSUMER "gpio-utils"
24
25/**
26 * doc: Operation of gpio
27 *
28 * Provide the api of gpiochip for chardev interface. There are two
29 * types of api. The first one provide as same function as each
30 * ioctl, including request and release for lines of gpio, read/write
31 * the value of gpio. If the user want to do lots of read and write of
32 * lines of gpio, user should use this type of api.
33 *
34 * The second one provide the easy to use api for user. Each of the
35 * following api will request gpio lines, do the operation and then
36 * release these lines.
37 */
38/**
39 * gpiotools_request_linehandle() - request gpio lines in a gpiochip
40 * @device_name: The name of gpiochip without prefix "/dev/",
41 * such as "gpiochip0"
42 * @lines: An array desired lines, specified by offset
43 * index for the associated GPIO device.
44 * @nline: The number of lines to request.
45 * @flag: The new flag for requsted gpio. Reference
46 * "linux/gpio.h" for the meaning of flag.
47 * @data: Default value will be set to gpio when flag is
48 * GPIOHANDLE_REQUEST_OUTPUT.
49 * @consumer_label: The name of consumer, such as "sysfs",
50 * "powerkey". This is useful for other users to
51 * know who is using.
52 *
53 * Request gpio lines through the ioctl provided by chardev. User
54 * could call gpiotools_set_values() and gpiotools_get_values() to
55 * read and write respectively through the returned fd. Call
56 * gpiotools_release_linehandle() to release these lines after that.
57 *
58 * Return: On success return the fd;
59 * On failure return the errno.
60 */
61int gpiotools_request_linehandle(const char *device_name, unsigned int *lines,
62 unsigned int nlines, unsigned int flag,
63 struct gpiohandle_data *data,
64 const char *consumer_label)
65{
66 struct gpiohandle_request req;
67 char *chrdev_name;
68 int fd;
69 int i;
70 int ret;
71
72 ret = asprintf(&chrdev_name, "/dev/%s", device_name);
73 if (ret < 0)
74 return -ENOMEM;
75
76 fd = open(chrdev_name, 0);
77 if (fd == -1) {
78 ret = -errno;
79 fprintf(stderr, "Failed to open %s\n", chrdev_name);
80 goto exit_close_error;
81 }
82
83 for (i = 0; i < nlines; i++)
84 req.lineoffsets[i] = lines[i];
85
86 req.flags = flag;
87 strcpy(req.consumer_label, consumer_label);
88 req.lines = nlines;
89 if (flag & GPIOHANDLE_REQUEST_OUTPUT)
90 memcpy(req.default_values, data, sizeof(req.default_values));
91
92 ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
93 if (ret == -1) {
94 ret = -errno;
95 fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n",
96 ret);
97 }
98
99exit_close_error:
100 if (close(fd) == -1)
101 perror("Failed to close GPIO character device file");
102 free(chrdev_name);
103 return ret < 0 ? ret : req.fd;
104}
105/**
106 * gpiotools_set_values(): Set the value of gpio(s)
107 * @fd: The fd returned by
108 * gpiotools_request_linehandle().
109 * @data: The array of values want to set.
110 *
111 * Return: On success return 0;
112 * On failure return the errno.
113 */
114int gpiotools_set_values(const int fd, struct gpiohandle_data *data)
115{
116 int ret;
117
118 ret = ioctl(fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, data);
119 if (ret == -1) {
120 ret = -errno;
121 fprintf(stderr, "Failed to issue %s (%d)\n",
122 "GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret);
123 }
124
125 return ret;
126}
127
128/**
129 * gpiotools_get_values(): Get the value of gpio(s)
130 * @fd: The fd returned by
131 * gpiotools_request_linehandle().
132 * @data: The array of values get from hardware.
133 *
134 * Return: On success return 0;
135 * On failure return the errno.
136 */
137int gpiotools_get_values(const int fd, struct gpiohandle_data *data)
138{
139 int ret;
140
141 ret = ioctl(fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, data);
142 if (ret == -1) {
143 ret = -errno;
144 fprintf(stderr, "Failed to issue %s (%d)\n",
145 "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret);
146 }
147
148 return ret;
149}
150
151/**
152 * gpiotools_release_linehandle(): Release the line(s) of gpiochip
153 * @fd: The fd returned by
154 * gpiotools_request_linehandle().
155 *
156 * Return: On success return 0;
157 * On failure return the errno.
158 */
159int gpiotools_release_linehandle(const int fd)
160{
161 int ret;
162
163 ret = close(fd);
164 if (ret == -1) {
165 perror("Failed to close GPIO LINEHANDLE device file");
166 ret = -errno;
167 }
168
169 return ret;
170}
171
172/**
173 * gpiotools_get(): Get value from specific line
174 * @device_name: The name of gpiochip without prefix "/dev/",
175 * such as "gpiochip0"
176 * @line: number of line, such as 2.
177 *
178 * Return: On success return 0;
179 * On failure return the errno.
180 */
181int gpiotools_get(const char *device_name, unsigned int line)
182{
183 struct gpiohandle_data data;
184 unsigned int lines[] = {line};
185
186 gpiotools_gets(device_name, lines, 1, &data);
187 return data.values[0];
188}
189
190
191/**
192 * gpiotools_gets(): Get values from specific lines.
193 * @device_name: The name of gpiochip without prefix "/dev/",
194 * such as "gpiochip0".
195 * @lines: An array desired lines, specified by offset
196 * index for the associated GPIO device.
197 * @nline: The number of lines to request.
198 * @data: The array of values get from gpiochip.
199 *
200 * Return: On success return 0;
201 * On failure return the errno.
202 */
203int gpiotools_gets(const char *device_name, unsigned int *lines,
204 unsigned int nlines, struct gpiohandle_data *data)
205{
206 int fd;
207 int ret;
208 int ret_close;
209
210 ret = gpiotools_request_linehandle(device_name, lines, nlines,
211 GPIOHANDLE_REQUEST_INPUT, data,
212 COMSUMER);
213 if (ret < 0)
214 return ret;
215
216 fd = ret;
217 ret = gpiotools_get_values(fd, data);
218 ret_close = gpiotools_release_linehandle(fd);
219 return ret < 0 ? ret : ret_close;
220}
221
222/**
223 * gpiotools_set(): Set value to specific line
224 * @device_name: The name of gpiochip without prefix "/dev/",
225 * such as "gpiochip0"
226 * @line: number of line, such as 2.
227 * @value: The value of gpio, must be 0(low) or 1(high).
228 *
229 * Return: On success return 0;
230 * On failure return the errno.
231 */
232int gpiotools_set(const char *device_name, unsigned int line,
233 unsigned int value)
234{
235 struct gpiohandle_data data;
236 unsigned int lines[] = {line};
237
238 data.values[0] = value;
239 return gpiotools_sets(device_name, lines, 1, &data);
240}
241
242/**
243 * gpiotools_sets(): Set values to specific lines.
244 * @device_name: The name of gpiochip without prefix "/dev/",
245 * such as "gpiochip0".
246 * @lines: An array desired lines, specified by offset
247 * index for the associated GPIO device.
248 * @nline: The number of lines to request.
249 * @data: The array of values set to gpiochip, must be
250 * 0(low) or 1(high).
251 *
252 * Return: On success return 0;
253 * On failure return the errno.
254 */
255int gpiotools_sets(const char *device_name, unsigned int *lines,
256 unsigned int nlines, struct gpiohandle_data *data)
257{
258 int ret;
259
260 ret = gpiotools_request_linehandle(device_name, lines, nlines,
261 GPIOHANDLE_REQUEST_OUTPUT, data,
262 COMSUMER);
263 if (ret < 0)
264 return ret;
265
266 return gpiotools_release_linehandle(ret);
267}
diff --git a/tools/gpio/gpio-utils.h b/tools/gpio/gpio-utils.h
index 5f57133b8c04..344ea041f8d4 100644
--- a/tools/gpio/gpio-utils.h
+++ b/tools/gpio/gpio-utils.h
@@ -24,4 +24,20 @@ static inline int check_prefix(const char *str, const char *prefix)
24 strncmp(str, prefix, strlen(prefix)) == 0; 24 strncmp(str, prefix, strlen(prefix)) == 0;
25} 25}
26 26
27int gpiotools_request_linehandle(const char *device_name, unsigned int *lines,
28 unsigned int nlines, unsigned int flag,
29 struct gpiohandle_data *data,
30 const char *consumer_label);
31int gpiotools_set_values(const int fd, struct gpiohandle_data *data);
32int gpiotools_get_values(const int fd, struct gpiohandle_data *data);
33int gpiotools_release_linehandle(const int fd);
34
35int gpiotools_get(const char *device_name, unsigned int line);
36int gpiotools_gets(const char *device_name, unsigned int *lines,
37 unsigned int nlines, struct gpiohandle_data *data);
38int gpiotools_set(const char *device_name, unsigned int line,
39 unsigned int value);
40int gpiotools_sets(const char *device_name, unsigned int *lines,
41 unsigned int nlines, struct gpiohandle_data *data);
42
27#endif /* _GPIO_UTILS_H_ */ 43#endif /* _GPIO_UTILS_H_ */
diff --git a/tools/hv/Makefile b/tools/hv/Makefile
index a8c4644022a6..0d1e61b81844 100644
--- a/tools/hv/Makefile
+++ b/tools/hv/Makefile
@@ -1,9 +1,8 @@
1# Makefile for Hyper-V tools 1# Makefile for Hyper-V tools
2 2
3CC = $(CROSS_COMPILE)gcc 3CC = $(CROSS_COMPILE)gcc
4PTHREAD_LIBS = -lpthread
5WARNINGS = -Wall -Wextra 4WARNINGS = -Wall -Wextra
6CFLAGS = $(WARNINGS) -g $(PTHREAD_LIBS) $(shell getconf LFS_CFLAGS) 5CFLAGS = $(WARNINGS) -g $(shell getconf LFS_CFLAGS)
7 6
8CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include 7CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include
9 8
diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c
index fdc9ca4c0356..26ae609a9448 100644
--- a/tools/hv/hv_fcopy_daemon.c
+++ b/tools/hv/hv_fcopy_daemon.c
@@ -18,21 +18,14 @@
18 18
19 19
20#include <sys/types.h> 20#include <sys/types.h>
21#include <sys/socket.h>
22#include <sys/poll.h>
23#include <linux/types.h>
24#include <linux/kdev_t.h>
25#include <stdio.h> 21#include <stdio.h>
26#include <stdlib.h> 22#include <stdlib.h>
27#include <unistd.h> 23#include <unistd.h>
28#include <string.h>
29#include <ctype.h>
30#include <errno.h> 24#include <errno.h>
31#include <linux/hyperv.h> 25#include <linux/hyperv.h>
32#include <syslog.h> 26#include <syslog.h>
33#include <sys/stat.h> 27#include <sys/stat.h>
34#include <fcntl.h> 28#include <fcntl.h>
35#include <dirent.h>
36#include <getopt.h> 29#include <getopt.h>
37 30
38static int target_fd; 31static int target_fd;
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index bc7adb84e679..f1758fcbc37d 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -22,8 +22,6 @@
22 */ 22 */
23 23
24 24
25#include <sys/types.h>
26#include <sys/socket.h>
27#include <sys/poll.h> 25#include <sys/poll.h>
28#include <sys/utsname.h> 26#include <sys/utsname.h>
29#include <stdio.h> 27#include <stdio.h>
@@ -34,7 +32,6 @@
34#include <errno.h> 32#include <errno.h>
35#include <arpa/inet.h> 33#include <arpa/inet.h>
36#include <linux/hyperv.h> 34#include <linux/hyperv.h>
37#include <linux/netlink.h>
38#include <ifaddrs.h> 35#include <ifaddrs.h>
39#include <netdb.h> 36#include <netdb.h>
40#include <syslog.h> 37#include <syslog.h>
@@ -96,13 +93,13 @@ static struct utsname uts_buf;
96 93
97#define KVP_CONFIG_LOC "/var/lib/hyperv" 94#define KVP_CONFIG_LOC "/var/lib/hyperv"
98 95
96#ifndef KVP_SCRIPTS_PATH
97#define KVP_SCRIPTS_PATH "/usr/libexec/hypervkvpd/"
98#endif
99
99#define MAX_FILE_NAME 100 100#define MAX_FILE_NAME 100
100#define ENTRIES_PER_BLOCK 50 101#define ENTRIES_PER_BLOCK 50
101 102
102#ifndef SOL_NETLINK
103#define SOL_NETLINK 270
104#endif
105
106struct kvp_record { 103struct kvp_record {
107 char key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; 104 char key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
108 char value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; 105 char value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
@@ -702,7 +699,7 @@ static char *kvp_mac_to_if_name(char *mac)
702 if (dir == NULL) 699 if (dir == NULL)
703 return NULL; 700 return NULL;
704 701
705 snprintf(dev_id, sizeof(dev_id), kvp_net_dir); 702 snprintf(dev_id, sizeof(dev_id), "%s", kvp_net_dir);
706 q = dev_id + strlen(kvp_net_dir); 703 q = dev_id + strlen(kvp_net_dir);
707 704
708 while ((entry = readdir(dir)) != NULL) { 705 while ((entry = readdir(dir)) != NULL) {
@@ -825,7 +822,7 @@ static void kvp_get_ipconfig_info(char *if_name,
825 * . 822 * .
826 */ 823 */
827 824
828 sprintf(cmd, "%s", "hv_get_dns_info"); 825 sprintf(cmd, KVP_SCRIPTS_PATH "%s", "hv_get_dns_info");
829 826
830 /* 827 /*
831 * Execute the command to gather DNS info. 828 * Execute the command to gather DNS info.
@@ -842,7 +839,7 @@ static void kvp_get_ipconfig_info(char *if_name,
842 * Enabled: DHCP enabled. 839 * Enabled: DHCP enabled.
843 */ 840 */
844 841
845 sprintf(cmd, "%s %s", "hv_get_dhcp_info", if_name); 842 sprintf(cmd, KVP_SCRIPTS_PATH "%s %s", "hv_get_dhcp_info", if_name);
846 843
847 file = popen(cmd, "r"); 844 file = popen(cmd, "r");
848 if (file == NULL) 845 if (file == NULL)
@@ -1348,7 +1345,8 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
1348 * invoke the external script to do its magic. 1345 * invoke the external script to do its magic.
1349 */ 1346 */
1350 1347
1351 snprintf(cmd, sizeof(cmd), "%s %s", "hv_set_ifconfig", if_file); 1348 snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s",
1349 "hv_set_ifconfig", if_file);
1352 if (system(cmd)) { 1350 if (system(cmd)) {
1353 syslog(LOG_ERR, "Failed to execute cmd '%s'; error: %d %s", 1351 syslog(LOG_ERR, "Failed to execute cmd '%s'; error: %d %s",
1354 cmd, errno, strerror(errno)); 1352 cmd, errno, strerror(errno));
diff --git a/tools/iio/iio_generic_buffer.c b/tools/iio/iio_generic_buffer.c
index f39c0e9c0d5c..f0c6f54a8b2f 100644
--- a/tools/iio/iio_generic_buffer.c
+++ b/tools/iio/iio_generic_buffer.c
@@ -247,6 +247,7 @@ void print_usage(void)
247 fprintf(stderr, "Usage: generic_buffer [options]...\n" 247 fprintf(stderr, "Usage: generic_buffer [options]...\n"
248 "Capture, convert and output data from IIO device buffer\n" 248 "Capture, convert and output data from IIO device buffer\n"
249 " -a Auto-activate all available channels\n" 249 " -a Auto-activate all available channels\n"
250 " -A Force-activate ALL channels\n"
250 " -c <n> Do n conversions\n" 251 " -c <n> Do n conversions\n"
251 " -e Disable wait for event (new data)\n" 252 " -e Disable wait for event (new data)\n"
252 " -g Use trigger-less mode\n" 253 " -g Use trigger-less mode\n"
@@ -347,16 +348,22 @@ int main(int argc, char **argv)
347 int noevents = 0; 348 int noevents = 0;
348 int notrigger = 0; 349 int notrigger = 0;
349 char *dummy; 350 char *dummy;
351 bool force_autochannels = false;
350 352
351 struct iio_channel_info *channels = NULL; 353 struct iio_channel_info *channels = NULL;
352 354
353 register_cleanup(); 355 register_cleanup();
354 356
355 while ((c = getopt_long(argc, argv, "ac:egl:n:N:t:T:w:", longopts, NULL)) != -1) { 357 while ((c = getopt_long(argc, argv, "aAc:egl:n:N:t:T:w:?", longopts,
358 NULL)) != -1) {
356 switch (c) { 359 switch (c) {
357 case 'a': 360 case 'a':
358 autochannels = AUTOCHANNELS_ENABLED; 361 autochannels = AUTOCHANNELS_ENABLED;
359 break; 362 break;
363 case 'A':
364 autochannels = AUTOCHANNELS_ENABLED;
365 force_autochannels = true;
366 break;
360 case 'c': 367 case 'c':
361 errno = 0; 368 errno = 0;
362 num_loops = strtoul(optarg, &dummy, 10); 369 num_loops = strtoul(optarg, &dummy, 10);
@@ -519,15 +526,16 @@ int main(int argc, char **argv)
519 "diag %s\n", dev_dir_name); 526 "diag %s\n", dev_dir_name);
520 goto error; 527 goto error;
521 } 528 }
522 if (num_channels && autochannels == AUTOCHANNELS_ENABLED) { 529 if (num_channels && autochannels == AUTOCHANNELS_ENABLED &&
530 !force_autochannels) {
523 fprintf(stderr, "Auto-channels selected but some channels " 531 fprintf(stderr, "Auto-channels selected but some channels "
524 "are already activated in sysfs\n"); 532 "are already activated in sysfs\n");
525 fprintf(stderr, "Proceeding without activating any channels\n"); 533 fprintf(stderr, "Proceeding without activating any channels\n");
526 } 534 }
527 535
528 if (!num_channels && autochannels == AUTOCHANNELS_ENABLED) { 536 if ((!num_channels && autochannels == AUTOCHANNELS_ENABLED) ||
529 fprintf(stderr, 537 (autochannels == AUTOCHANNELS_ENABLED && force_autochannels)) {
530 "No channels are enabled, enabling all channels\n"); 538 fprintf(stderr, "Enabling all channels\n");
531 539
532 ret = enable_disable_all_channels(dev_dir_name, 1); 540 ret = enable_disable_all_channels(dev_dir_name, 1);
533 if (ret) { 541 if (ret) {
diff --git a/tools/include/asm/bug.h b/tools/include/asm/bug.h
index 9e5f4846967f..beda1a884b50 100644
--- a/tools/include/asm/bug.h
+++ b/tools/include/asm/bug.h
@@ -12,6 +12,17 @@
12 unlikely(__ret_warn_on); \ 12 unlikely(__ret_warn_on); \
13}) 13})
14 14
15#define WARN_ON_ONCE(condition) ({ \
16 static int __warned; \
17 int __ret_warn_once = !!(condition); \
18 \
19 if (unlikely(__ret_warn_once && !__warned)) { \
20 __warned = true; \
21 WARN_ON(1); \
22 } \
23 unlikely(__ret_warn_once); \
24})
25
15#define WARN_ONCE(condition, format...) ({ \ 26#define WARN_ONCE(condition, format...) ({ \
16 static int __warned; \ 27 static int __warned; \
17 int __ret_warn_once = !!(condition); \ 28 int __ret_warn_once = !!(condition); \
diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index 43c1c5021e4b..eef41d500e9e 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -35,6 +35,32 @@ static inline void bitmap_zero(unsigned long *dst, int nbits)
35 } 35 }
36} 36}
37 37
38static inline void bitmap_fill(unsigned long *dst, unsigned int nbits)
39{
40 unsigned int nlongs = BITS_TO_LONGS(nbits);
41 if (!small_const_nbits(nbits)) {
42 unsigned int len = (nlongs - 1) * sizeof(unsigned long);
43 memset(dst, 0xff, len);
44 }
45 dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits);
46}
47
48static inline int bitmap_empty(const unsigned long *src, unsigned nbits)
49{
50 if (small_const_nbits(nbits))
51 return ! (*src & BITMAP_LAST_WORD_MASK(nbits));
52
53 return find_first_bit(src, nbits) == nbits;
54}
55
56static inline int bitmap_full(const unsigned long *src, unsigned int nbits)
57{
58 if (small_const_nbits(nbits))
59 return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits));
60
61 return find_first_zero_bit(src, nbits) == nbits;
62}
63
38static inline int bitmap_weight(const unsigned long *src, int nbits) 64static inline int bitmap_weight(const unsigned long *src, int nbits)
39{ 65{
40 if (small_const_nbits(nbits)) 66 if (small_const_nbits(nbits))
diff --git a/tools/include/linux/types.h b/tools/include/linux/types.h
index 8ebf6278b2ef..c24b3e3ae296 100644
--- a/tools/include/linux/types.h
+++ b/tools/include/linux/types.h
@@ -42,11 +42,7 @@ typedef __s8 s8;
42#else 42#else
43#define __bitwise__ 43#define __bitwise__
44#endif 44#endif
45#ifdef __CHECK_ENDIAN__
46#define __bitwise __bitwise__ 45#define __bitwise __bitwise__
47#else
48#define __bitwise
49#endif
50 46
51#define __force 47#define __force
52#define __user 48#define __user
diff --git a/tools/include/uapi/linux/hw_breakpoint.h b/tools/include/uapi/linux/hw_breakpoint.h
index b04000a2296a..2b65efd19a46 100644
--- a/tools/include/uapi/linux/hw_breakpoint.h
+++ b/tools/include/uapi/linux/hw_breakpoint.h
@@ -4,7 +4,11 @@
4enum { 4enum {
5 HW_BREAKPOINT_LEN_1 = 1, 5 HW_BREAKPOINT_LEN_1 = 1,
6 HW_BREAKPOINT_LEN_2 = 2, 6 HW_BREAKPOINT_LEN_2 = 2,
7 HW_BREAKPOINT_LEN_3 = 3,
7 HW_BREAKPOINT_LEN_4 = 4, 8 HW_BREAKPOINT_LEN_4 = 4,
9 HW_BREAKPOINT_LEN_5 = 5,
10 HW_BREAKPOINT_LEN_6 = 6,
11 HW_BREAKPOINT_LEN_7 = 7,
8 HW_BREAKPOINT_LEN_8 = 8, 12 HW_BREAKPOINT_LEN_8 = 8,
9}; 13};
10 14
diff --git a/tools/leds/.gitignore b/tools/leds/.gitignore
new file mode 100644
index 000000000000..ac96d9f53dfc
--- /dev/null
+++ b/tools/leds/.gitignore
@@ -0,0 +1 @@
uledmon
diff --git a/tools/leds/Makefile b/tools/leds/Makefile
new file mode 100644
index 000000000000..c03a79ebf9c8
--- /dev/null
+++ b/tools/leds/Makefile
@@ -0,0 +1,13 @@
1# Makefile for LEDs tools
2
3CC = $(CROSS_COMPILE)gcc
4CFLAGS = -Wall -Wextra -g -I../../include/uapi
5
6all: uledmon
7%: %.c
8 $(CC) $(CFLAGS) -o $@ $^
9
10clean:
11 $(RM) uledmon
12
13.PHONY: all clean
diff --git a/tools/leds/uledmon.c b/tools/leds/uledmon.c
new file mode 100644
index 000000000000..25cbc7acf50a
--- /dev/null
+++ b/tools/leds/uledmon.c
@@ -0,0 +1,63 @@
1/*
2 * uledmon.c
3 *
4 * This program creates a new userspace LED class device and monitors it. A
5 * timestamp and brightness value is printed each time the brightness changes.
6 *
7 * Usage: uledmon <device-name>
8 *
9 * <device-name> is the name of the LED class device to be created. Pressing
10 * CTRL+C will exit.
11 */
12
13#include <fcntl.h>
14#include <stdio.h>
15#include <string.h>
16#include <time.h>
17#include <unistd.h>
18
19#include <linux/uleds.h>
20
21int main(int argc, char const *argv[])
22{
23 struct uleds_user_dev uleds_dev;
24 int fd, ret;
25 int brightness;
26 struct timespec ts;
27
28 if (argc != 2) {
29 fprintf(stderr, "Requires <device-name> argument\n");
30 return 1;
31 }
32
33 strncpy(uleds_dev.name, argv[1], LED_MAX_NAME_SIZE);
34 uleds_dev.max_brightness = 100;
35
36 fd = open("/dev/uleds", O_RDWR);
37 if (fd == -1) {
38 perror("Failed to open /dev/uleds");
39 return 1;
40 }
41
42 ret = write(fd, &uleds_dev, sizeof(uleds_dev));
43 if (ret == -1) {
44 perror("Failed to write to /dev/uleds");
45 close(fd);
46 return 1;
47 }
48
49 while (1) {
50 ret = read(fd, &brightness, sizeof(brightness));
51 if (ret == -1) {
52 perror("Failed to read from /dev/uleds");
53 close(fd);
54 return 1;
55 }
56 clock_gettime(CLOCK_MONOTONIC, &ts);
57 printf("[%ld.%09ld] %u\n", ts.tv_sec, ts.tv_nsec, brightness);
58 }
59
60 close(fd);
61
62 return 0;
63}
diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile
index 0a6fda9837f7..adba83b325d5 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -2,7 +2,7 @@ include ../../scripts/Makefile.include
2include ../../scripts/utilities.mak # QUIET_CLEAN 2include ../../scripts/utilities.mak # QUIET_CLEAN
3 3
4ifeq ($(srctree),) 4ifeq ($(srctree),)
5srctree := $(patsubst %/,%,$(dir $(shell pwd))) 5srctree := $(patsubst %/,%,$(dir $(CURDIR)))
6srctree := $(patsubst %/,%,$(dir $(srctree))) 6srctree := $(patsubst %/,%,$(dir $(srctree)))
7srctree := $(patsubst %/,%,$(dir $(srctree))) 7srctree := $(patsubst %/,%,$(dir $(srctree)))
8#$(info Determined 'srctree' to be $(srctree)) 8#$(info Determined 'srctree' to be $(srctree))
diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index 62d89d50fcbd..e2efddf10231 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -7,7 +7,7 @@ BPF_EXTRAVERSION = 1
7MAKEFLAGS += --no-print-directory 7MAKEFLAGS += --no-print-directory
8 8
9ifeq ($(srctree),) 9ifeq ($(srctree),)
10srctree := $(patsubst %/,%,$(dir $(shell pwd))) 10srctree := $(patsubst %/,%,$(dir $(CURDIR)))
11srctree := $(patsubst %/,%,$(dir $(srctree))) 11srctree := $(patsubst %/,%,$(dir $(srctree)))
12srctree := $(patsubst %/,%,$(dir $(srctree))) 12srctree := $(patsubst %/,%,$(dir $(srctree)))
13#$(info Determined 'srctree' to be $(srctree)) 13#$(info Determined 'srctree' to be $(srctree))
diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
index 1d57af56814b..3bc0ef9f8923 100644
--- a/tools/lib/lockdep/Makefile
+++ b/tools/lib/lockdep/Makefile
@@ -50,7 +50,7 @@ ifndef VERBOSE
50endif 50endif
51 51
52ifeq ($(srctree),) 52ifeq ($(srctree),)
53srctree := $(patsubst %/,%,$(dir $(shell pwd))) 53srctree := $(patsubst %/,%,$(dir $(CURDIR)))
54srctree := $(patsubst %/,%,$(dir $(srctree))) 54srctree := $(patsubst %/,%,$(dir $(srctree)))
55srctree := $(patsubst %/,%,$(dir $(srctree))) 55srctree := $(patsubst %/,%,$(dir $(srctree)))
56#$(info Determined 'srctree' to be $(srctree)) 56#$(info Determined 'srctree' to be $(srctree))
diff --git a/tools/lib/subcmd/Makefile b/tools/lib/subcmd/Makefile
index ce4b7e527566..3f8cc44a0dbd 100644
--- a/tools/lib/subcmd/Makefile
+++ b/tools/lib/subcmd/Makefile
@@ -2,7 +2,7 @@ include ../../scripts/Makefile.include
2include ../../scripts/utilities.mak # QUIET_CLEAN 2include ../../scripts/utilities.mak # QUIET_CLEAN
3 3
4ifeq ($(srctree),) 4ifeq ($(srctree),)
5srctree := $(patsubst %/,%,$(dir $(shell pwd))) 5srctree := $(patsubst %/,%,$(dir $(CURDIR)))
6srctree := $(patsubst %/,%,$(dir $(srctree))) 6srctree := $(patsubst %/,%,$(dir $(srctree)))
7srctree := $(patsubst %/,%,$(dir $(srctree))) 7srctree := $(patsubst %/,%,$(dir $(srctree)))
8#$(info Determined 'srctree' to be $(srctree)) 8#$(info Determined 'srctree' to be $(srctree))
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index c76012ebdb9c..2616c66e10c1 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -86,7 +86,7 @@ ifndef VERBOSE
86endif 86endif
87 87
88ifeq ($(srctree),) 88ifeq ($(srctree),)
89srctree := $(patsubst %/,%,$(dir $(shell pwd))) 89srctree := $(patsubst %/,%,$(dir $(CURDIR)))
90srctree := $(patsubst %/,%,$(dir $(srctree))) 90srctree := $(patsubst %/,%,$(dir $(srctree)))
91srctree := $(patsubst %/,%,$(dir $(srctree))) 91srctree := $(patsubst %/,%,$(dir $(srctree)))
92#$(info Determined 'srctree' to be $(srctree)) 92#$(info Determined 'srctree' to be $(srctree))
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index 041b493ad3ab..27e019c09bd2 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -11,12 +11,12 @@ LD = ld
11AR = ar 11AR = ar
12 12
13ifeq ($(srctree),) 13ifeq ($(srctree),)
14srctree := $(patsubst %/,%,$(dir $(shell pwd))) 14srctree := $(patsubst %/,%,$(dir $(CURDIR)))
15srctree := $(patsubst %/,%,$(dir $(srctree))) 15srctree := $(patsubst %/,%,$(dir $(srctree)))
16endif 16endif
17 17
18SUBCMD_SRCDIR = $(srctree)/tools/lib/subcmd/ 18SUBCMD_SRCDIR = $(srctree)/tools/lib/subcmd/
19LIBSUBCMD_OUTPUT = $(if $(OUTPUT),$(OUTPUT),$(PWD)/) 19LIBSUBCMD_OUTPUT = $(if $(OUTPUT),$(OUTPUT),$(CURDIR)/)
20LIBSUBCMD = $(LIBSUBCMD_OUTPUT)libsubcmd.a 20LIBSUBCMD = $(LIBSUBCMD_OUTPUT)libsubcmd.a
21 21
22OBJTOOL := $(OUTPUT)objtool 22OBJTOOL := $(OUTPUT)objtool
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 8f1c258b151a..e5af38eede17 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -100,7 +100,7 @@ LC_NUMERIC=C
100export LC_COLLATE LC_NUMERIC 100export LC_COLLATE LC_NUMERIC
101 101
102ifeq ($(srctree),) 102ifeq ($(srctree),)
103srctree := $(patsubst %/,%,$(dir $(shell pwd))) 103srctree := $(patsubst %/,%,$(dir $(CURDIR)))
104srctree := $(patsubst %/,%,$(dir $(srctree))) 104srctree := $(patsubst %/,%,$(dir $(srctree)))
105#$(info Determined 'srctree' to be $(srctree)) 105#$(info Determined 'srctree' to be $(srctree))
106endif 106endif
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 0784748f1670..e46723568516 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -42,7 +42,7 @@ LC_NUMERIC=C
42export LC_COLLATE LC_NUMERIC 42export LC_COLLATE LC_NUMERIC
43 43
44ifeq ($(srctree),) 44ifeq ($(srctree),)
45srctree := $(patsubst %/,%,$(dir $(shell pwd))) 45srctree := $(patsubst %/,%,$(dir $(CURDIR)))
46srctree := $(patsubst %/,%,$(dir $(srctree))) 46srctree := $(patsubst %/,%,$(dir $(srctree)))
47#$(info Determined 'srctree' to be $(srctree)) 47#$(info Determined 'srctree' to be $(srctree))
48endif 48endif
diff --git a/tools/power/acpi/os_specific/service_layers/osunixxf.c b/tools/power/acpi/os_specific/service_layers/osunixxf.c
index 8d8003c919d4..10648aaf6164 100644
--- a/tools/power/acpi/os_specific/service_layers/osunixxf.c
+++ b/tools/power/acpi/os_specific/service_layers/osunixxf.c
@@ -646,8 +646,12 @@ acpi_os_create_semaphore(u32 max_units,
646 } 646 }
647#ifdef __APPLE__ 647#ifdef __APPLE__
648 { 648 {
649 char *semaphore_name = tmpnam(NULL); 649 static int semaphore_count = 0;
650 char semaphore_name[32];
650 651
652 snprintf(semaphore_name, sizeof(semaphore_name), "acpi_sem_%d",
653 semaphore_count++);
654 printf("%s\n", semaphore_name);
651 sem = 655 sem =
652 sem_open(semaphore_name, O_EXCL | O_CREAT, 0755, 656 sem_open(semaphore_name, O_EXCL | O_CREAT, 0755,
653 initial_units); 657 initial_units);
@@ -692,10 +696,15 @@ acpi_status acpi_os_delete_semaphore(acpi_handle handle)
692 if (!sem) { 696 if (!sem) {
693 return (AE_BAD_PARAMETER); 697 return (AE_BAD_PARAMETER);
694 } 698 }
695 699#ifdef __APPLE__
700 if (sem_close(sem) == -1) {
701 return (AE_BAD_PARAMETER);
702 }
703#else
696 if (sem_destroy(sem) == -1) { 704 if (sem_destroy(sem) == -1) {
697 return (AE_BAD_PARAMETER); 705 return (AE_BAD_PARAMETER);
698 } 706 }
707#endif
699 708
700 return (AE_OK); 709 return (AE_OK);
701} 710}
diff --git a/tools/power/acpi/tools/ec/ec_access.c b/tools/power/acpi/tools/ec/ec_access.c
index 6b8aaed44f2c..5f50642386db 100644
--- a/tools/power/acpi/tools/ec/ec_access.c
+++ b/tools/power/acpi/tools/ec/ec_access.c
@@ -46,7 +46,7 @@ void usage(char progname[], int exit_status)
46 puts("\t-b offset : Read value at byte_offset (in hex)"); 46 puts("\t-b offset : Read value at byte_offset (in hex)");
47 puts("\t-w offset -v value : Write value at byte_offset"); 47 puts("\t-w offset -v value : Write value at byte_offset");
48 puts("\t-h : Print this help\n\n"); 48 puts("\t-h : Print this help\n\n");
49 puts("Offsets and values are in hexadecimal number sytem."); 49 puts("Offsets and values are in hexadecimal number system.");
50 puts("The offset and value must be between 0 and 0xff."); 50 puts("The offset and value must be between 0 and 0xff.");
51 exit(exit_status); 51 exit(exit_status);
52} 52}
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
index 8358863259c5..d6e1c02ddcfe 100644
--- a/tools/power/cpupower/Makefile
+++ b/tools/power/cpupower/Makefile
@@ -108,9 +108,6 @@ MKDIR = mkdir
108# Now we set up the build system 108# Now we set up the build system
109# 109#
110 110
111# set up PWD so that older versions of make will work with our build.
112PWD = $(shell pwd)
113
114GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo $(OUTPUT)po/$$HLANG.gmo; done;} 111GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo $(OUTPUT)po/$$HLANG.gmo; done;}
115 112
116export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS 113export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS
diff --git a/tools/power/cpupower/debug/kernel/Makefile b/tools/power/cpupower/debug/kernel/Makefile
index 96b146fe6f8d..a8a6f8eec5c2 100644
--- a/tools/power/cpupower/debug/kernel/Makefile
+++ b/tools/power/cpupower/debug/kernel/Makefile
@@ -1,7 +1,6 @@
1obj-m := 1obj-m :=
2 2
3KDIR := /lib/modules/$(shell uname -r)/build 3KDIR := /lib/modules/$(shell uname -r)/build
4PWD := $(shell pwd)
5KMISC := /lib/modules/$(shell uname -r)/cpufrequtils/ 4KMISC := /lib/modules/$(shell uname -r)/cpufrequtils/
6 5
7ifeq ("$(CONFIG_X86_TSC)", "y") 6ifeq ("$(CONFIG_X86_TSC)", "y")
@@ -9,7 +8,7 @@ ifeq ("$(CONFIG_X86_TSC)", "y")
9endif 8endif
10 9
11default: 10default:
12 $(MAKE) -C $(KDIR) M=$(PWD) 11 $(MAKE) -C $(KDIR) M=$(CURDIR)
13 12
14clean: 13clean:
15 - rm -rf *.o *.ko .tmp-versions .*.cmd .*.mod.* *.mod.c 14 - rm -rf *.o *.ko .tmp-versions .*.cmd .*.mod.* *.mod.c
diff --git a/tools/spi/spidev_test.c b/tools/spi/spidev_test.c
index f046b77cfefe..816f119c9b7b 100644
--- a/tools/spi/spidev_test.c
+++ b/tools/spi/spidev_test.c
@@ -315,7 +315,7 @@ static void transfer_file(int fd, char *filename)
315 pabort("can't stat input file"); 315 pabort("can't stat input file");
316 316
317 tx_fd = open(filename, O_RDONLY); 317 tx_fd = open(filename, O_RDONLY);
318 if (fd < 0) 318 if (tx_fd < 0)
319 pabort("can't open input file"); 319 pabort("can't open input file");
320 320
321 tx = malloc(sb.st_size); 321 tx = malloc(sb.st_size);
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index d08e214ec6e7..be93ab02b490 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -719,14 +719,14 @@ sub set_value {
719 719
720 if ($buildonly && $lvalue =~ /^TEST_TYPE(\[.*\])?$/ && $prvalue ne "build") { 720 if ($buildonly && $lvalue =~ /^TEST_TYPE(\[.*\])?$/ && $prvalue ne "build") {
721 # Note if a test is something other than build, then we 721 # Note if a test is something other than build, then we
722 # will need other manditory options. 722 # will need other mandatory options.
723 if ($prvalue ne "install") { 723 if ($prvalue ne "install") {
724 # for bisect, we need to check BISECT_TYPE 724 # for bisect, we need to check BISECT_TYPE
725 if ($prvalue ne "bisect") { 725 if ($prvalue ne "bisect") {
726 $buildonly = 0; 726 $buildonly = 0;
727 } 727 }
728 } else { 728 } else {
729 # install still limits some manditory options. 729 # install still limits some mandatory options.
730 $buildonly = 2; 730 $buildonly = 2;
731 } 731 }
732 } 732 }
@@ -735,7 +735,7 @@ sub set_value {
735 if ($prvalue ne "install") { 735 if ($prvalue ne "install") {
736 $buildonly = 0; 736 $buildonly = 0;
737 } else { 737 } else {
738 # install still limits some manditory options. 738 # install still limits some mandatory options.
739 $buildonly = 2; 739 $buildonly = 2;
740 } 740 }
741 } 741 }
@@ -3989,7 +3989,7 @@ sub make_min_config {
3989 } 3989 }
3990 } 3990 }
3991 3991
3992 # Save off all the current mandidory configs 3992 # Save off all the current mandatory configs
3993 open (OUT, ">$temp_config") 3993 open (OUT, ">$temp_config")
3994 or die "Can't write to $temp_config"; 3994 or die "Can't write to $temp_config";
3995 foreach my $config (keys %keep_configs) { 3995 foreach my $config (keys %keep_configs) {
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile
index f2e07f2fd4b4..3635e4d3eca7 100644
--- a/tools/testing/radix-tree/Makefile
+++ b/tools/testing/radix-tree/Makefile
@@ -1,10 +1,14 @@
1 1
2CFLAGS += -I. -g -O2 -Wall -D_LGPL_SOURCE 2CFLAGS += -I. -I../../include -g -O2 -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 multiorder.o \ 6 regression1.o regression2.o regression3.o multiorder.o \
7 iteration_check.o 7 iteration_check.o benchmark.o
8
9ifdef BENCHMARK
10 CFLAGS += -DBENCHMARK=1
11endif
8 12
9targets: $(TARGETS) 13targets: $(TARGETS)
10 14
@@ -14,7 +18,12 @@ main: $(OFILES)
14clean: 18clean:
15 $(RM) -f $(TARGETS) *.o radix-tree.c 19 $(RM) -f $(TARGETS) *.o radix-tree.c
16 20
17$(OFILES): *.h */*.h ../../../include/linux/radix-tree.h ../../include/linux/*.h 21find_next_bit.o: ../../lib/find_bit.c
22 $(CC) $(CFLAGS) -c -o $@ $<
23
24$(OFILES): *.h */*.h \
25 ../../include/linux/*.h \
26 ../../../include/linux/radix-tree.h
18 27
19radix-tree.c: ../../../lib/radix-tree.c 28radix-tree.c: ../../../lib/radix-tree.c
20 sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@ 29 sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@
diff --git a/tools/testing/radix-tree/benchmark.c b/tools/testing/radix-tree/benchmark.c
new file mode 100644
index 000000000000..215ca86c7605
--- /dev/null
+++ b/tools/testing/radix-tree/benchmark.c
@@ -0,0 +1,98 @@
1/*
2 * benchmark.c:
3 * Author: Konstantin Khlebnikov <koct9i@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 */
14#include <linux/radix-tree.h>
15#include <linux/slab.h>
16#include <linux/errno.h>
17#include <time.h>
18#include "test.h"
19
20#define NSEC_PER_SEC 1000000000L
21
22static long long benchmark_iter(struct radix_tree_root *root, bool tagged)
23{
24 volatile unsigned long sink = 0;
25 struct radix_tree_iter iter;
26 struct timespec start, finish;
27 long long nsec;
28 int l, loops = 1;
29 void **slot;
30
31#ifdef BENCHMARK
32again:
33#endif
34 clock_gettime(CLOCK_MONOTONIC, &start);
35 for (l = 0; l < loops; l++) {
36 if (tagged) {
37 radix_tree_for_each_tagged(slot, root, &iter, 0, 0)
38 sink ^= (unsigned long)slot;
39 } else {
40 radix_tree_for_each_slot(slot, root, &iter, 0)
41 sink ^= (unsigned long)slot;
42 }
43 }
44 clock_gettime(CLOCK_MONOTONIC, &finish);
45
46 nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC +
47 (finish.tv_nsec - start.tv_nsec);
48
49#ifdef BENCHMARK
50 if (loops == 1 && nsec * 5 < NSEC_PER_SEC) {
51 loops = NSEC_PER_SEC / nsec / 4 + 1;
52 goto again;
53 }
54#endif
55
56 nsec /= loops;
57 return nsec;
58}
59
60static void benchmark_size(unsigned long size, unsigned long step, int order)
61{
62 RADIX_TREE(tree, GFP_KERNEL);
63 long long normal, tagged;
64 unsigned long index;
65
66 for (index = 0 ; index < size ; index += step) {
67 item_insert_order(&tree, index, order);
68 radix_tree_tag_set(&tree, index, 0);
69 }
70
71 tagged = benchmark_iter(&tree, true);
72 normal = benchmark_iter(&tree, false);
73
74 printf("Size %ld, step %6ld, order %d tagged %10lld ns, normal %10lld ns\n",
75 size, step, order, tagged, normal);
76
77 item_kill_tree(&tree);
78 rcu_barrier();
79}
80
81void benchmark(void)
82{
83 unsigned long size[] = {1 << 10, 1 << 20, 0};
84 unsigned long step[] = {1, 2, 7, 15, 63, 64, 65,
85 128, 256, 512, 12345, 0};
86 int c, s;
87
88 printf("starting benchmarks\n");
89 printf("RADIX_TREE_MAP_SHIFT = %d\n", RADIX_TREE_MAP_SHIFT);
90
91 for (c = 0; size[c]; c++)
92 for (s = 0; step[s]; s++)
93 benchmark_size(size[c], step[s], 0);
94
95 for (c = 0; size[c]; c++)
96 for (s = 0; step[s]; s++)
97 benchmark_size(size[c], step[s] << 9, 9);
98}
diff --git a/tools/testing/radix-tree/find_next_bit.c b/tools/testing/radix-tree/find_next_bit.c
deleted file mode 100644
index d1c2178bb2d4..000000000000
--- a/tools/testing/radix-tree/find_next_bit.c
+++ /dev/null
@@ -1,57 +0,0 @@
1/* find_next_bit.c: fallback find next bit implementation
2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#include <linux/types.h>
13#include <linux/bitops.h>
14
15#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
16
17/*
18 * Find the next set bit in a memory region.
19 */
20unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
21 unsigned long offset)
22{
23 const unsigned long *p = addr + BITOP_WORD(offset);
24 unsigned long result = offset & ~(BITS_PER_LONG-1);
25 unsigned long tmp;
26
27 if (offset >= size)
28 return size;
29 size -= result;
30 offset %= BITS_PER_LONG;
31 if (offset) {
32 tmp = *(p++);
33 tmp &= (~0UL << offset);
34 if (size < BITS_PER_LONG)
35 goto found_first;
36 if (tmp)
37 goto found_middle;
38 size -= BITS_PER_LONG;
39 result += BITS_PER_LONG;
40 }
41 while (size & ~(BITS_PER_LONG-1)) {
42 if ((tmp = *(p++)))
43 goto found_middle;
44 result += BITS_PER_LONG;
45 size -= BITS_PER_LONG;
46 }
47 if (!size)
48 return result;
49 tmp = *p;
50
51found_first:
52 tmp &= (~0UL >> (BITS_PER_LONG - size));
53 if (tmp == 0UL) /* Are any bits set? */
54 return result + size; /* Nope. */
55found_middle:
56 return result + __ffs(tmp);
57}
diff --git a/tools/testing/radix-tree/iteration_check.c b/tools/testing/radix-tree/iteration_check.c
index 9adb8e7415a6..7572b7ed930e 100644
--- a/tools/testing/radix-tree/iteration_check.c
+++ b/tools/testing/radix-tree/iteration_check.c
@@ -16,35 +16,50 @@
16#include <pthread.h> 16#include <pthread.h>
17#include "test.h" 17#include "test.h"
18 18
19#define NUM_THREADS 4 19#define NUM_THREADS 5
20#define TAG 0 20#define MAX_IDX 100
21#define TAG 0
22#define NEW_TAG 1
23
21static pthread_mutex_t tree_lock = PTHREAD_MUTEX_INITIALIZER; 24static pthread_mutex_t tree_lock = PTHREAD_MUTEX_INITIALIZER;
22static pthread_t threads[NUM_THREADS]; 25static pthread_t threads[NUM_THREADS];
23RADIX_TREE(tree, GFP_KERNEL); 26static unsigned int seeds[3];
24bool test_complete; 27static RADIX_TREE(tree, GFP_KERNEL);
28static bool test_complete;
29static int max_order;
25 30
26/* relentlessly fill the tree with tagged entries */ 31/* relentlessly fill the tree with tagged entries */
27static void *add_entries_fn(void *arg) 32static void *add_entries_fn(void *arg)
28{ 33{
29 int pgoff; 34 rcu_register_thread();
30 35
31 while (!test_complete) { 36 while (!test_complete) {
32 for (pgoff = 0; pgoff < 100; pgoff++) { 37 unsigned long pgoff;
38 int order;
39
40 for (pgoff = 0; pgoff < MAX_IDX; pgoff++) {
33 pthread_mutex_lock(&tree_lock); 41 pthread_mutex_lock(&tree_lock);
34 if (item_insert(&tree, pgoff) == 0) 42 for (order = max_order; order >= 0; order--) {
35 item_tag_set(&tree, pgoff, TAG); 43 if (item_insert_order(&tree, pgoff, order)
44 == 0) {
45 item_tag_set(&tree, pgoff, TAG);
46 break;
47 }
48 }
36 pthread_mutex_unlock(&tree_lock); 49 pthread_mutex_unlock(&tree_lock);
37 } 50 }
38 } 51 }
39 52
53 rcu_unregister_thread();
54
40 return NULL; 55 return NULL;
41} 56}
42 57
43/* 58/*
44 * Iterate over the tagged entries, doing a radix_tree_iter_retry() as we find 59 * Iterate over the tagged entries, doing a radix_tree_iter_retry() as we find
45 * things that have been removed and randomly resetting our iteration to the 60 * things that have been removed and randomly resetting our iteration to the
46 * next chunk with radix_tree_iter_next(). Both radix_tree_iter_retry() and 61 * next chunk with radix_tree_iter_resume(). Both radix_tree_iter_retry() and
47 * radix_tree_iter_next() cause radix_tree_next_slot() to be called with a 62 * radix_tree_iter_resume() cause radix_tree_next_slot() to be called with a
48 * NULL 'slot' variable. 63 * NULL 'slot' variable.
49 */ 64 */
50static void *tagged_iteration_fn(void *arg) 65static void *tagged_iteration_fn(void *arg)
@@ -52,17 +67,12 @@ static void *tagged_iteration_fn(void *arg)
52 struct radix_tree_iter iter; 67 struct radix_tree_iter iter;
53 void **slot; 68 void **slot;
54 69
70 rcu_register_thread();
71
55 while (!test_complete) { 72 while (!test_complete) {
56 rcu_read_lock(); 73 rcu_read_lock();
57 radix_tree_for_each_tagged(slot, &tree, &iter, 0, TAG) { 74 radix_tree_for_each_tagged(slot, &tree, &iter, 0, TAG) {
58 void *entry; 75 void *entry = radix_tree_deref_slot(slot);
59 int i;
60
61 /* busy wait to let removals happen */
62 for (i = 0; i < 1000000; i++)
63 ;
64
65 entry = radix_tree_deref_slot(slot);
66 if (unlikely(!entry)) 76 if (unlikely(!entry))
67 continue; 77 continue;
68 78
@@ -71,20 +81,26 @@ static void *tagged_iteration_fn(void *arg)
71 continue; 81 continue;
72 } 82 }
73 83
74 if (rand() % 50 == 0) 84 if (rand_r(&seeds[0]) % 50 == 0) {
75 slot = radix_tree_iter_next(&iter); 85 slot = radix_tree_iter_resume(slot, &iter);
86 rcu_read_unlock();
87 rcu_barrier();
88 rcu_read_lock();
89 }
76 } 90 }
77 rcu_read_unlock(); 91 rcu_read_unlock();
78 } 92 }
79 93
94 rcu_unregister_thread();
95
80 return NULL; 96 return NULL;
81} 97}
82 98
83/* 99/*
84 * Iterate over the entries, doing a radix_tree_iter_retry() as we find things 100 * Iterate over the entries, doing a radix_tree_iter_retry() as we find things
85 * that have been removed and randomly resetting our iteration to the next 101 * that have been removed and randomly resetting our iteration to the next
86 * chunk with radix_tree_iter_next(). Both radix_tree_iter_retry() and 102 * chunk with radix_tree_iter_resume(). Both radix_tree_iter_retry() and
87 * radix_tree_iter_next() cause radix_tree_next_slot() to be called with a 103 * radix_tree_iter_resume() cause radix_tree_next_slot() to be called with a
88 * NULL 'slot' variable. 104 * NULL 'slot' variable.
89 */ 105 */
90static void *untagged_iteration_fn(void *arg) 106static void *untagged_iteration_fn(void *arg)
@@ -92,17 +108,12 @@ static void *untagged_iteration_fn(void *arg)
92 struct radix_tree_iter iter; 108 struct radix_tree_iter iter;
93 void **slot; 109 void **slot;
94 110
111 rcu_register_thread();
112
95 while (!test_complete) { 113 while (!test_complete) {
96 rcu_read_lock(); 114 rcu_read_lock();
97 radix_tree_for_each_slot(slot, &tree, &iter, 0) { 115 radix_tree_for_each_slot(slot, &tree, &iter, 0) {
98 void *entry; 116 void *entry = radix_tree_deref_slot(slot);
99 int i;
100
101 /* busy wait to let removals happen */
102 for (i = 0; i < 1000000; i++)
103 ;
104
105 entry = radix_tree_deref_slot(slot);
106 if (unlikely(!entry)) 117 if (unlikely(!entry))
107 continue; 118 continue;
108 119
@@ -111,12 +122,18 @@ static void *untagged_iteration_fn(void *arg)
111 continue; 122 continue;
112 } 123 }
113 124
114 if (rand() % 50 == 0) 125 if (rand_r(&seeds[1]) % 50 == 0) {
115 slot = radix_tree_iter_next(&iter); 126 slot = radix_tree_iter_resume(slot, &iter);
127 rcu_read_unlock();
128 rcu_barrier();
129 rcu_read_lock();
130 }
116 } 131 }
117 rcu_read_unlock(); 132 rcu_read_unlock();
118 } 133 }
119 134
135 rcu_unregister_thread();
136
120 return NULL; 137 return NULL;
121} 138}
122 139
@@ -126,47 +143,71 @@ static void *untagged_iteration_fn(void *arg)
126 */ 143 */
127static void *remove_entries_fn(void *arg) 144static void *remove_entries_fn(void *arg)
128{ 145{
146 rcu_register_thread();
147
129 while (!test_complete) { 148 while (!test_complete) {
130 int pgoff; 149 int pgoff;
131 150
132 pgoff = rand() % 100; 151 pgoff = rand_r(&seeds[2]) % MAX_IDX;
133 152
134 pthread_mutex_lock(&tree_lock); 153 pthread_mutex_lock(&tree_lock);
135 item_delete(&tree, pgoff); 154 item_delete(&tree, pgoff);
136 pthread_mutex_unlock(&tree_lock); 155 pthread_mutex_unlock(&tree_lock);
137 } 156 }
138 157
158 rcu_unregister_thread();
159
160 return NULL;
161}
162
163static void *tag_entries_fn(void *arg)
164{
165 rcu_register_thread();
166
167 while (!test_complete) {
168 tag_tagged_items(&tree, &tree_lock, 0, MAX_IDX, 10, TAG,
169 NEW_TAG);
170 }
171 rcu_unregister_thread();
139 return NULL; 172 return NULL;
140} 173}
141 174
142/* This is a unit test for a bug found by the syzkaller tester */ 175/* This is a unit test for a bug found by the syzkaller tester */
143void iteration_test(void) 176void iteration_test(unsigned order, unsigned test_duration)
144{ 177{
145 int i; 178 int i;
146 179
147 printf("Running iteration tests for 10 seconds\n"); 180 printf("Running %siteration tests for %d seconds\n",
181 order > 0 ? "multiorder " : "", test_duration);
148 182
149 srand(time(0)); 183 max_order = order;
150 test_complete = false; 184 test_complete = false;
151 185
186 for (i = 0; i < 3; i++)
187 seeds[i] = rand();
188
152 if (pthread_create(&threads[0], NULL, tagged_iteration_fn, NULL)) { 189 if (pthread_create(&threads[0], NULL, tagged_iteration_fn, NULL)) {
153 perror("pthread_create"); 190 perror("create tagged iteration thread");
154 exit(1); 191 exit(1);
155 } 192 }
156 if (pthread_create(&threads[1], NULL, untagged_iteration_fn, NULL)) { 193 if (pthread_create(&threads[1], NULL, untagged_iteration_fn, NULL)) {
157 perror("pthread_create"); 194 perror("create untagged iteration thread");
158 exit(1); 195 exit(1);
159 } 196 }
160 if (pthread_create(&threads[2], NULL, add_entries_fn, NULL)) { 197 if (pthread_create(&threads[2], NULL, add_entries_fn, NULL)) {
161 perror("pthread_create"); 198 perror("create add entry thread");
162 exit(1); 199 exit(1);
163 } 200 }
164 if (pthread_create(&threads[3], NULL, remove_entries_fn, NULL)) { 201 if (pthread_create(&threads[3], NULL, remove_entries_fn, NULL)) {
165 perror("pthread_create"); 202 perror("create remove entry thread");
203 exit(1);
204 }
205 if (pthread_create(&threads[4], NULL, tag_entries_fn, NULL)) {
206 perror("create tag entry thread");
166 exit(1); 207 exit(1);
167 } 208 }
168 209
169 sleep(10); 210 sleep(test_duration);
170 test_complete = true; 211 test_complete = true;
171 212
172 for (i = 0; i < NUM_THREADS; i++) { 213 for (i = 0; i < NUM_THREADS; i++) {
diff --git a/tools/testing/radix-tree/linux.c b/tools/testing/radix-tree/linux.c
index 154823737b20..d31ea7c9abec 100644
--- a/tools/testing/radix-tree/linux.c
+++ b/tools/testing/radix-tree/linux.c
@@ -1,14 +1,26 @@
1#include <stdlib.h> 1#include <stdlib.h>
2#include <string.h> 2#include <string.h>
3#include <malloc.h> 3#include <malloc.h>
4#include <pthread.h>
4#include <unistd.h> 5#include <unistd.h>
5#include <assert.h> 6#include <assert.h>
6 7
7#include <linux/mempool.h> 8#include <linux/mempool.h>
9#include <linux/poison.h>
8#include <linux/slab.h> 10#include <linux/slab.h>
11#include <linux/radix-tree.h>
9#include <urcu/uatomic.h> 12#include <urcu/uatomic.h>
10 13
11int nr_allocated; 14int nr_allocated;
15int preempt_count;
16
17struct kmem_cache {
18 pthread_mutex_t lock;
19 int size;
20 int nr_objs;
21 void *objs;
22 void (*ctor)(void *);
23};
12 24
13void *mempool_alloc(mempool_t *pool, int gfp_mask) 25void *mempool_alloc(mempool_t *pool, int gfp_mask)
14{ 26{
@@ -33,19 +45,59 @@ mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
33 45
34void *kmem_cache_alloc(struct kmem_cache *cachep, int flags) 46void *kmem_cache_alloc(struct kmem_cache *cachep, int flags)
35{ 47{
36 void *ret = malloc(cachep->size); 48 struct radix_tree_node *node;
37 if (cachep->ctor) 49
38 cachep->ctor(ret); 50 if (flags & __GFP_NOWARN)
51 return NULL;
52
53 pthread_mutex_lock(&cachep->lock);
54 if (cachep->nr_objs) {
55 cachep->nr_objs--;
56 node = cachep->objs;
57 cachep->objs = node->private_data;
58 pthread_mutex_unlock(&cachep->lock);
59 node->private_data = NULL;
60 } else {
61 pthread_mutex_unlock(&cachep->lock);
62 node = malloc(cachep->size);
63 if (cachep->ctor)
64 cachep->ctor(node);
65 }
66
39 uatomic_inc(&nr_allocated); 67 uatomic_inc(&nr_allocated);
40 return ret; 68 return node;
41} 69}
42 70
43void kmem_cache_free(struct kmem_cache *cachep, void *objp) 71void kmem_cache_free(struct kmem_cache *cachep, void *objp)
44{ 72{
45 assert(objp); 73 assert(objp);
46 uatomic_dec(&nr_allocated); 74 uatomic_dec(&nr_allocated);
47 memset(objp, 0, cachep->size); 75 pthread_mutex_lock(&cachep->lock);
48 free(objp); 76 if (cachep->nr_objs > 10) {
77 memset(objp, POISON_FREE, cachep->size);
78 free(objp);
79 } else {
80 struct radix_tree_node *node = objp;
81 cachep->nr_objs++;
82 node->private_data = cachep->objs;
83 cachep->objs = node;
84 }
85 pthread_mutex_unlock(&cachep->lock);
86}
87
88void *kmalloc(size_t size, gfp_t gfp)
89{
90 void *ret = malloc(size);
91 uatomic_inc(&nr_allocated);
92 return ret;
93}
94
95void kfree(void *p)
96{
97 if (!p)
98 return;
99 uatomic_dec(&nr_allocated);
100 free(p);
49} 101}
50 102
51struct kmem_cache * 103struct kmem_cache *
@@ -54,7 +106,10 @@ kmem_cache_create(const char *name, size_t size, size_t offset,
54{ 106{
55 struct kmem_cache *ret = malloc(sizeof(*ret)); 107 struct kmem_cache *ret = malloc(sizeof(*ret));
56 108
109 pthread_mutex_init(&ret->lock, NULL);
57 ret->size = size; 110 ret->size = size;
111 ret->nr_objs = 0;
112 ret->objs = NULL;
58 ret->ctor = ctor; 113 ret->ctor = ctor;
59 return ret; 114 return ret;
60} 115}
diff --git a/tools/testing/radix-tree/linux/bitops.h b/tools/testing/radix-tree/linux/bitops.h
index 71d58427ab60..a13e9bc76eec 100644
--- a/tools/testing/radix-tree/linux/bitops.h
+++ b/tools/testing/radix-tree/linux/bitops.h
@@ -2,9 +2,14 @@
2#define _ASM_GENERIC_BITOPS_NON_ATOMIC_H_ 2#define _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5#include <linux/bitops/find.h>
6#include <linux/bitops/hweight.h>
7#include <linux/kernel.h>
5 8
6#define BITOP_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) 9#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
7#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) 10#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
11#define BITS_PER_BYTE 8
12#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
8 13
9/** 14/**
10 * __set_bit - Set a bit in memory 15 * __set_bit - Set a bit in memory
@@ -17,16 +22,16 @@
17 */ 22 */
18static inline void __set_bit(int nr, volatile unsigned long *addr) 23static inline void __set_bit(int nr, volatile unsigned long *addr)
19{ 24{
20 unsigned long mask = BITOP_MASK(nr); 25 unsigned long mask = BIT_MASK(nr);
21 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); 26 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
22 27
23 *p |= mask; 28 *p |= mask;
24} 29}
25 30
26static inline void __clear_bit(int nr, volatile unsigned long *addr) 31static inline void __clear_bit(int nr, volatile unsigned long *addr)
27{ 32{
28 unsigned long mask = BITOP_MASK(nr); 33 unsigned long mask = BIT_MASK(nr);
29 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); 34 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
30 35
31 *p &= ~mask; 36 *p &= ~mask;
32} 37}
@@ -42,8 +47,8 @@ static inline void __clear_bit(int nr, volatile unsigned long *addr)
42 */ 47 */
43static inline void __change_bit(int nr, volatile unsigned long *addr) 48static inline void __change_bit(int nr, volatile unsigned long *addr)
44{ 49{
45 unsigned long mask = BITOP_MASK(nr); 50 unsigned long mask = BIT_MASK(nr);
46 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); 51 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
47 52
48 *p ^= mask; 53 *p ^= mask;
49} 54}
@@ -59,8 +64,8 @@ static inline void __change_bit(int nr, volatile unsigned long *addr)
59 */ 64 */
60static inline int __test_and_set_bit(int nr, volatile unsigned long *addr) 65static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
61{ 66{
62 unsigned long mask = BITOP_MASK(nr); 67 unsigned long mask = BIT_MASK(nr);
63 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); 68 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
64 unsigned long old = *p; 69 unsigned long old = *p;
65 70
66 *p = old | mask; 71 *p = old | mask;
@@ -78,8 +83,8 @@ static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
78 */ 83 */
79static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr) 84static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
80{ 85{
81 unsigned long mask = BITOP_MASK(nr); 86 unsigned long mask = BIT_MASK(nr);
82 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); 87 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
83 unsigned long old = *p; 88 unsigned long old = *p;
84 89
85 *p = old & ~mask; 90 *p = old & ~mask;
@@ -90,8 +95,8 @@ static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
90static inline int __test_and_change_bit(int nr, 95static inline int __test_and_change_bit(int nr,
91 volatile unsigned long *addr) 96 volatile unsigned long *addr)
92{ 97{
93 unsigned long mask = BITOP_MASK(nr); 98 unsigned long mask = BIT_MASK(nr);
94 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); 99 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
95 unsigned long old = *p; 100 unsigned long old = *p;
96 101
97 *p = old ^ mask; 102 *p = old ^ mask;
@@ -105,7 +110,7 @@ static inline int __test_and_change_bit(int nr,
105 */ 110 */
106static inline int test_bit(int nr, const volatile unsigned long *addr) 111static inline int test_bit(int nr, const volatile unsigned long *addr)
107{ 112{
108 return 1UL & (addr[BITOP_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); 113 return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
109} 114}
110 115
111/** 116/**
@@ -147,4 +152,9 @@ unsigned long find_next_bit(const unsigned long *addr,
147 unsigned long size, 152 unsigned long size,
148 unsigned long offset); 153 unsigned long offset);
149 154
155static inline unsigned long hweight_long(unsigned long w)
156{
157 return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
158}
159
150#endif /* _ASM_GENERIC_BITOPS_NON_ATOMIC_H_ */ 160#endif /* _ASM_GENERIC_BITOPS_NON_ATOMIC_H_ */
diff --git a/tools/testing/radix-tree/linux/bitops/non-atomic.h b/tools/testing/radix-tree/linux/bitops/non-atomic.h
index 46a825cf2ae1..6a1bcb9d2c4a 100644
--- a/tools/testing/radix-tree/linux/bitops/non-atomic.h
+++ b/tools/testing/radix-tree/linux/bitops/non-atomic.h
@@ -3,7 +3,6 @@
3 3
4#include <asm/types.h> 4#include <asm/types.h>
5 5
6#define BITOP_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
7#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) 6#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
8 7
9/** 8/**
@@ -17,7 +16,7 @@
17 */ 16 */
18static inline void __set_bit(int nr, volatile unsigned long *addr) 17static inline void __set_bit(int nr, volatile unsigned long *addr)
19{ 18{
20 unsigned long mask = BITOP_MASK(nr); 19 unsigned long mask = BIT_MASK(nr);
21 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); 20 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
22 21
23 *p |= mask; 22 *p |= mask;
@@ -25,7 +24,7 @@ static inline void __set_bit(int nr, volatile unsigned long *addr)
25 24
26static inline void __clear_bit(int nr, volatile unsigned long *addr) 25static inline void __clear_bit(int nr, volatile unsigned long *addr)
27{ 26{
28 unsigned long mask = BITOP_MASK(nr); 27 unsigned long mask = BIT_MASK(nr);
29 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); 28 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
30 29
31 *p &= ~mask; 30 *p &= ~mask;
@@ -42,7 +41,7 @@ static inline void __clear_bit(int nr, volatile unsigned long *addr)
42 */ 41 */
43static inline void __change_bit(int nr, volatile unsigned long *addr) 42static inline void __change_bit(int nr, volatile unsigned long *addr)
44{ 43{
45 unsigned long mask = BITOP_MASK(nr); 44 unsigned long mask = BIT_MASK(nr);
46 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); 45 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
47 46
48 *p ^= mask; 47 *p ^= mask;
@@ -59,7 +58,7 @@ static inline void __change_bit(int nr, volatile unsigned long *addr)
59 */ 58 */
60static inline int __test_and_set_bit(int nr, volatile unsigned long *addr) 59static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
61{ 60{
62 unsigned long mask = BITOP_MASK(nr); 61 unsigned long mask = BIT_MASK(nr);
63 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); 62 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
64 unsigned long old = *p; 63 unsigned long old = *p;
65 64
@@ -78,7 +77,7 @@ static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
78 */ 77 */
79static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr) 78static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
80{ 79{
81 unsigned long mask = BITOP_MASK(nr); 80 unsigned long mask = BIT_MASK(nr);
82 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); 81 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
83 unsigned long old = *p; 82 unsigned long old = *p;
84 83
@@ -90,7 +89,7 @@ static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
90static inline int __test_and_change_bit(int nr, 89static inline int __test_and_change_bit(int nr,
91 volatile unsigned long *addr) 90 volatile unsigned long *addr)
92{ 91{
93 unsigned long mask = BITOP_MASK(nr); 92 unsigned long mask = BIT_MASK(nr);
94 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); 93 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
95 unsigned long old = *p; 94 unsigned long old = *p;
96 95
diff --git a/tools/testing/radix-tree/linux/bug.h b/tools/testing/radix-tree/linux/bug.h
index ccbe444977df..23b8ed52f8c8 100644
--- a/tools/testing/radix-tree/linux/bug.h
+++ b/tools/testing/radix-tree/linux/bug.h
@@ -1 +1 @@
#define WARN_ON_ONCE(x) assert(x) #include "asm/bug.h"
diff --git a/tools/testing/radix-tree/linux/cpu.h b/tools/testing/radix-tree/linux/cpu.h
index 7cf412103205..a45530d78107 100644
--- a/tools/testing/radix-tree/linux/cpu.h
+++ b/tools/testing/radix-tree/linux/cpu.h
@@ -1,21 +1 @@
1 #define cpuhp_setup_state_nocalls(a, b, c, d) (0)
2#define hotcpu_notifier(a, b)
3
4#define CPU_ONLINE 0x0002 /* CPU (unsigned)v is up */
5#define CPU_UP_PREPARE 0x0003 /* CPU (unsigned)v coming up */
6#define CPU_UP_CANCELED 0x0004 /* CPU (unsigned)v NOT coming up */
7#define CPU_DOWN_PREPARE 0x0005 /* CPU (unsigned)v going down */
8#define CPU_DOWN_FAILED 0x0006 /* CPU (unsigned)v NOT going down */
9#define CPU_DEAD 0x0007 /* CPU (unsigned)v dead */
10#define CPU_POST_DEAD 0x0009 /* CPU (unsigned)v dead, cpu_hotplug
11 * lock is dropped */
12#define CPU_BROKEN 0x000C /* CPU (unsigned)v did not die properly,
13 * perhaps due to preemption. */
14#define CPU_TASKS_FROZEN 0x0010
15
16#define CPU_ONLINE_FROZEN (CPU_ONLINE | CPU_TASKS_FROZEN)
17#define CPU_UP_PREPARE_FROZEN (CPU_UP_PREPARE | CPU_TASKS_FROZEN)
18#define CPU_UP_CANCELED_FROZEN (CPU_UP_CANCELED | CPU_TASKS_FROZEN)
19#define CPU_DOWN_PREPARE_FROZEN (CPU_DOWN_PREPARE | CPU_TASKS_FROZEN)
20#define CPU_DOWN_FAILED_FROZEN (CPU_DOWN_FAILED | CPU_TASKS_FROZEN)
21#define CPU_DEAD_FROZEN (CPU_DEAD | CPU_TASKS_FROZEN)
diff --git a/tools/testing/radix-tree/linux/gfp.h b/tools/testing/radix-tree/linux/gfp.h
index 5201b915f631..5b09b2ce6c33 100644
--- a/tools/testing/radix-tree/linux/gfp.h
+++ b/tools/testing/radix-tree/linux/gfp.h
@@ -3,8 +3,24 @@
3 3
4#define __GFP_BITS_SHIFT 26 4#define __GFP_BITS_SHIFT 26
5#define __GFP_BITS_MASK ((gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) 5#define __GFP_BITS_MASK ((gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
6#define __GFP_WAIT 1 6
7#define __GFP_ACCOUNT 0 7#define __GFP_HIGH 0x20u
8#define __GFP_NOWARN 0 8#define __GFP_IO 0x40u
9#define __GFP_FS 0x80u
10#define __GFP_NOWARN 0x200u
11#define __GFP_ATOMIC 0x80000u
12#define __GFP_ACCOUNT 0x100000u
13#define __GFP_DIRECT_RECLAIM 0x400000u
14#define __GFP_KSWAPD_RECLAIM 0x2000000u
15
16#define __GFP_RECLAIM (__GFP_DIRECT_RECLAIM|__GFP_KSWAPD_RECLAIM)
17
18#define GFP_ATOMIC (__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)
19#define GFP_KERNEL (__GFP_RECLAIM | __GFP_IO | __GFP_FS)
20
21static inline bool gfpflags_allow_blocking(const gfp_t gfp_flags)
22{
23 return !!(gfp_flags & __GFP_DIRECT_RECLAIM);
24}
9 25
10#endif 26#endif
diff --git a/tools/testing/radix-tree/linux/kernel.h b/tools/testing/radix-tree/linux/kernel.h
index be98a47b4e1b..9b43b4975d83 100644
--- a/tools/testing/radix-tree/linux/kernel.h
+++ b/tools/testing/radix-tree/linux/kernel.h
@@ -8,9 +8,14 @@
8#include <limits.h> 8#include <limits.h>
9 9
10#include "../../include/linux/compiler.h" 10#include "../../include/linux/compiler.h"
11#include "../../include/linux/err.h"
11#include "../../../include/linux/kconfig.h" 12#include "../../../include/linux/kconfig.h"
12 13
14#ifdef BENCHMARK
15#define RADIX_TREE_MAP_SHIFT 6
16#else
13#define RADIX_TREE_MAP_SHIFT 3 17#define RADIX_TREE_MAP_SHIFT 3
18#endif
14 19
15#ifndef NULL 20#ifndef NULL
16#define NULL 0 21#define NULL 0
@@ -43,4 +48,17 @@ static inline int in_interrupt(void)
43{ 48{
44 return 0; 49 return 0;
45} 50}
51
52/*
53 * This looks more complex than it should be. But we need to
54 * get the type for the ~ right in round_down (it needs to be
55 * as wide as the result!), and we want to evaluate the macro
56 * arguments just once each.
57 */
58#define __round_mask(x, y) ((__typeof__(x))((y)-1))
59#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
60#define round_down(x, y) ((x) & ~__round_mask(x, y))
61
62#define xchg(ptr, x) uatomic_xchg(ptr, x)
63
46#endif /* _KERNEL_H */ 64#endif /* _KERNEL_H */
diff --git a/tools/testing/radix-tree/linux/notifier.h b/tools/testing/radix-tree/linux/notifier.h
deleted file mode 100644
index 70e4797d5a46..000000000000
--- a/tools/testing/radix-tree/linux/notifier.h
+++ /dev/null
@@ -1,8 +0,0 @@
1#ifndef _NOTIFIER_H
2#define _NOTIFIER_H
3
4struct notifier_block;
5
6#define NOTIFY_OK 0x0001 /* Suits me */
7
8#endif
diff --git a/tools/testing/radix-tree/linux/preempt.h b/tools/testing/radix-tree/linux/preempt.h
index 6210672e3baa..65c04c226965 100644
--- a/tools/testing/radix-tree/linux/preempt.h
+++ b/tools/testing/radix-tree/linux/preempt.h
@@ -1,4 +1,4 @@
1/* */ 1extern int preempt_count;
2 2
3#define preempt_disable() do { } while (0) 3#define preempt_disable() uatomic_inc(&preempt_count)
4#define preempt_enable() do { } while (0) 4#define preempt_enable() uatomic_dec(&preempt_count)
diff --git a/tools/testing/radix-tree/linux/slab.h b/tools/testing/radix-tree/linux/slab.h
index 6d5a34770fd4..e40337f41a38 100644
--- a/tools/testing/radix-tree/linux/slab.h
+++ b/tools/testing/radix-tree/linux/slab.h
@@ -7,15 +7,8 @@
7#define SLAB_PANIC 2 7#define SLAB_PANIC 2
8#define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* Objects are reclaimable */ 8#define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* Objects are reclaimable */
9 9
10static inline int gfpflags_allow_blocking(gfp_t mask) 10void *kmalloc(size_t size, gfp_t);
11{ 11void kfree(void *);
12 return 1;
13}
14
15struct kmem_cache {
16 int size;
17 void (*ctor)(void *);
18};
19 12
20void *kmem_cache_alloc(struct kmem_cache *cachep, int flags); 13void *kmem_cache_alloc(struct kmem_cache *cachep, int flags);
21void kmem_cache_free(struct kmem_cache *cachep, void *objp); 14void kmem_cache_free(struct kmem_cache *cachep, void *objp);
diff --git a/tools/testing/radix-tree/linux/types.h b/tools/testing/radix-tree/linux/types.h
index faa0b6ff9ca8..8491d89873bb 100644
--- a/tools/testing/radix-tree/linux/types.h
+++ b/tools/testing/radix-tree/linux/types.h
@@ -6,8 +6,6 @@
6#define __rcu 6#define __rcu
7#define __read_mostly 7#define __read_mostly
8 8
9#define BITS_PER_LONG (sizeof(long) * 8)
10
11static inline void INIT_LIST_HEAD(struct list_head *list) 9static inline void INIT_LIST_HEAD(struct list_head *list)
12{ 10{
13 list->next = list; 11 list->next = list;
diff --git a/tools/testing/radix-tree/main.c b/tools/testing/radix-tree/main.c
index daa9010693e8..f7e9801a6754 100644
--- a/tools/testing/radix-tree/main.c
+++ b/tools/testing/radix-tree/main.c
@@ -67,7 +67,6 @@ void big_gang_check(bool long_run)
67 67
68 for (i = 0; i < (long_run ? 1000 : 3); i++) { 68 for (i = 0; i < (long_run ? 1000 : 3); i++) {
69 __big_gang_check(); 69 __big_gang_check();
70 srand(time(0));
71 printf("%d ", i); 70 printf("%d ", i);
72 fflush(stdout); 71 fflush(stdout);
73 } 72 }
@@ -206,8 +205,7 @@ void copy_tag_check(void)
206 } 205 }
207 206
208// printf("\ncopying tags...\n"); 207// printf("\ncopying tags...\n");
209 cur = start; 208 tagged = tag_tagged_items(&tree, NULL, start, end, ITEMS, 0, 1);
210 tagged = radix_tree_range_tag_if_tagged(&tree, &cur, end, ITEMS, 0, 1);
211 209
212// printf("checking copied tags\n"); 210// printf("checking copied tags\n");
213 assert(tagged == count); 211 assert(tagged == count);
@@ -215,16 +213,13 @@ void copy_tag_check(void)
215 213
216 /* Copy tags in several rounds */ 214 /* Copy tags in several rounds */
217// printf("\ncopying tags...\n"); 215// printf("\ncopying tags...\n");
218 cur = start; 216 tmp = rand() % (count / 10 + 2);
219 do { 217 tagged = tag_tagged_items(&tree, NULL, start, end, tmp, 0, 2);
220 tmp = rand() % (count/10+2); 218 assert(tagged == count);
221 tagged = radix_tree_range_tag_if_tagged(&tree, &cur, end, tmp, 0, 2);
222 } while (tmp == tagged);
223 219
224// printf("%lu %lu %lu\n", tagged, tmp, count); 220// printf("%lu %lu %lu\n", tagged, tmp, count);
225// printf("checking copied tags\n"); 221// printf("checking copied tags\n");
226 check_copied_tags(&tree, start, end, idx, ITEMS, 0, 2); 222 check_copied_tags(&tree, start, end, idx, ITEMS, 0, 2);
227 assert(tagged < tmp);
228 verify_tag_consistency(&tree, 0); 223 verify_tag_consistency(&tree, 0);
229 verify_tag_consistency(&tree, 1); 224 verify_tag_consistency(&tree, 1);
230 verify_tag_consistency(&tree, 2); 225 verify_tag_consistency(&tree, 2);
@@ -240,7 +235,7 @@ static void __locate_check(struct radix_tree_root *tree, unsigned long index,
240 235
241 item_insert_order(tree, index, order); 236 item_insert_order(tree, index, order);
242 item = item_lookup(tree, index); 237 item = item_lookup(tree, index);
243 index2 = radix_tree_locate_item(tree, item); 238 index2 = find_item(tree, item);
244 if (index != index2) { 239 if (index != index2) {
245 printf("index %ld order %d inserted; found %ld\n", 240 printf("index %ld order %d inserted; found %ld\n",
246 index, order, index2); 241 index, order, index2);
@@ -274,17 +269,17 @@ static void locate_check(void)
274 index += (1UL << order)) { 269 index += (1UL << order)) {
275 __locate_check(&tree, index + offset, order); 270 __locate_check(&tree, index + offset, order);
276 } 271 }
277 if (radix_tree_locate_item(&tree, &tree) != -1) 272 if (find_item(&tree, &tree) != -1)
278 abort(); 273 abort();
279 274
280 item_kill_tree(&tree); 275 item_kill_tree(&tree);
281 } 276 }
282 } 277 }
283 278
284 if (radix_tree_locate_item(&tree, &tree) != -1) 279 if (find_item(&tree, &tree) != -1)
285 abort(); 280 abort();
286 __locate_check(&tree, -1, 0); 281 __locate_check(&tree, -1, 0);
287 if (radix_tree_locate_item(&tree, &tree) != -1) 282 if (find_item(&tree, &tree) != -1)
288 abort(); 283 abort();
289 item_kill_tree(&tree); 284 item_kill_tree(&tree);
290} 285}
@@ -293,50 +288,80 @@ static void single_thread_tests(bool long_run)
293{ 288{
294 int i; 289 int i;
295 290
296 printf("starting single_thread_tests: %d allocated\n", nr_allocated); 291 printf("starting single_thread_tests: %d allocated, preempt %d\n",
292 nr_allocated, preempt_count);
297 multiorder_checks(); 293 multiorder_checks();
298 printf("after multiorder_check: %d allocated\n", nr_allocated); 294 rcu_barrier();
295 printf("after multiorder_check: %d allocated, preempt %d\n",
296 nr_allocated, preempt_count);
299 locate_check(); 297 locate_check();
300 printf("after locate_check: %d allocated\n", nr_allocated); 298 rcu_barrier();
299 printf("after locate_check: %d allocated, preempt %d\n",
300 nr_allocated, preempt_count);
301 tag_check(); 301 tag_check();
302 printf("after tag_check: %d allocated\n", nr_allocated); 302 rcu_barrier();
303 printf("after tag_check: %d allocated, preempt %d\n",
304 nr_allocated, preempt_count);
303 gang_check(); 305 gang_check();
304 printf("after gang_check: %d allocated\n", nr_allocated); 306 rcu_barrier();
307 printf("after gang_check: %d allocated, preempt %d\n",
308 nr_allocated, preempt_count);
305 add_and_check(); 309 add_and_check();
306 printf("after add_and_check: %d allocated\n", nr_allocated); 310 rcu_barrier();
311 printf("after add_and_check: %d allocated, preempt %d\n",
312 nr_allocated, preempt_count);
307 dynamic_height_check(); 313 dynamic_height_check();
308 printf("after dynamic_height_check: %d allocated\n", nr_allocated); 314 rcu_barrier();
315 printf("after dynamic_height_check: %d allocated, preempt %d\n",
316 nr_allocated, preempt_count);
309 big_gang_check(long_run); 317 big_gang_check(long_run);
310 printf("after big_gang_check: %d allocated\n", nr_allocated); 318 rcu_barrier();
319 printf("after big_gang_check: %d allocated, preempt %d\n",
320 nr_allocated, preempt_count);
311 for (i = 0; i < (long_run ? 2000 : 3); i++) { 321 for (i = 0; i < (long_run ? 2000 : 3); i++) {
312 copy_tag_check(); 322 copy_tag_check();
313 printf("%d ", i); 323 printf("%d ", i);
314 fflush(stdout); 324 fflush(stdout);
315 } 325 }
316 printf("after copy_tag_check: %d allocated\n", nr_allocated); 326 rcu_barrier();
327 printf("after copy_tag_check: %d allocated, preempt %d\n",
328 nr_allocated, preempt_count);
317} 329}
318 330
319int main(int argc, char **argv) 331int main(int argc, char **argv)
320{ 332{
321 bool long_run = false; 333 bool long_run = false;
322 int opt; 334 int opt;
335 unsigned int seed = time(NULL);
323 336
324 while ((opt = getopt(argc, argv, "l")) != -1) { 337 while ((opt = getopt(argc, argv, "ls:")) != -1) {
325 if (opt == 'l') 338 if (opt == 'l')
326 long_run = true; 339 long_run = true;
340 else if (opt == 's')
341 seed = strtoul(optarg, NULL, 0);
327 } 342 }
328 343
344 printf("random seed %u\n", seed);
345 srand(seed);
346
329 rcu_register_thread(); 347 rcu_register_thread();
330 radix_tree_init(); 348 radix_tree_init();
331 349
332 regression1_test(); 350 regression1_test();
333 regression2_test(); 351 regression2_test();
334 regression3_test(); 352 regression3_test();
335 iteration_test(); 353 iteration_test(0, 10);
354 iteration_test(7, 20);
336 single_thread_tests(long_run); 355 single_thread_tests(long_run);
337 356
338 sleep(1); 357 /* Free any remaining preallocated nodes */
339 printf("after sleep(1): %d allocated\n", nr_allocated); 358 radix_tree_cpu_dead(0);
359
360 benchmark();
361
362 rcu_barrier();
363 printf("after rcu_barrier: %d allocated, preempt %d\n",
364 nr_allocated, preempt_count);
340 rcu_unregister_thread(); 365 rcu_unregister_thread();
341 366
342 exit(0); 367 exit(0);
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c
index 05d7bc488971..f79812a5e070 100644
--- a/tools/testing/radix-tree/multiorder.c
+++ b/tools/testing/radix-tree/multiorder.c
@@ -26,7 +26,6 @@ static void __multiorder_tag_test(int index, int order)
26{ 26{
27 RADIX_TREE(tree, GFP_KERNEL); 27 RADIX_TREE(tree, GFP_KERNEL);
28 int base, err, i; 28 int base, err, i;
29 unsigned long first = 0;
30 29
31 /* our canonical entry */ 30 /* our canonical entry */
32 base = index & ~((1 << order) - 1); 31 base = index & ~((1 << order) - 1);
@@ -60,7 +59,7 @@ static void __multiorder_tag_test(int index, int order)
60 assert(!radix_tree_tag_get(&tree, i, 1)); 59 assert(!radix_tree_tag_get(&tree, i, 1));
61 } 60 }
62 61
63 assert(radix_tree_range_tag_if_tagged(&tree, &first, ~0UL, 10, 0, 1) == 1); 62 assert(tag_tagged_items(&tree, NULL, 0, ~0UL, 10, 0, 1) == 1);
64 assert(radix_tree_tag_clear(&tree, index, 0)); 63 assert(radix_tree_tag_clear(&tree, index, 0));
65 64
66 for_each_index(i, base, order) { 65 for_each_index(i, base, order) {
@@ -76,8 +75,27 @@ static void __multiorder_tag_test(int index, int order)
76 item_kill_tree(&tree); 75 item_kill_tree(&tree);
77} 76}
78 77
78static void __multiorder_tag_test2(unsigned order, unsigned long index2)
79{
80 RADIX_TREE(tree, GFP_KERNEL);
81 unsigned long index = (1 << order);
82 index2 += index;
83
84 assert(item_insert_order(&tree, 0, order) == 0);
85 assert(item_insert(&tree, index2) == 0);
86
87 assert(radix_tree_tag_set(&tree, 0, 0));
88 assert(radix_tree_tag_set(&tree, index2, 0));
89
90 assert(tag_tagged_items(&tree, NULL, 0, ~0UL, 10, 0, 1) == 2);
91
92 item_kill_tree(&tree);
93}
94
79static void multiorder_tag_tests(void) 95static void multiorder_tag_tests(void)
80{ 96{
97 int i, j;
98
81 /* test multi-order entry for indices 0-7 with no sibling pointers */ 99 /* test multi-order entry for indices 0-7 with no sibling pointers */
82 __multiorder_tag_test(0, 3); 100 __multiorder_tag_test(0, 3);
83 __multiorder_tag_test(5, 3); 101 __multiorder_tag_test(5, 3);
@@ -117,6 +135,10 @@ static void multiorder_tag_tests(void)
117 __multiorder_tag_test(300, 8); 135 __multiorder_tag_test(300, 8);
118 136
119 __multiorder_tag_test(0x12345678UL, 8); 137 __multiorder_tag_test(0x12345678UL, 8);
138
139 for (i = 1; i < 10; i++)
140 for (j = 0; j < (10 << i); j++)
141 __multiorder_tag_test2(i, j);
120} 142}
121 143
122static void multiorder_check(unsigned long index, int order) 144static void multiorder_check(unsigned long index, int order)
@@ -125,7 +147,7 @@ static void multiorder_check(unsigned long index, int order)
125 unsigned long min = index & ~((1UL << order) - 1); 147 unsigned long min = index & ~((1UL << order) - 1);
126 unsigned long max = min + (1UL << order); 148 unsigned long max = min + (1UL << order);
127 void **slot; 149 void **slot;
128 struct item *item2 = item_create(min); 150 struct item *item2 = item_create(min, order);
129 RADIX_TREE(tree, GFP_KERNEL); 151 RADIX_TREE(tree, GFP_KERNEL);
130 152
131 printf("Multiorder index %ld, order %d\n", index, order); 153 printf("Multiorder index %ld, order %d\n", index, order);
@@ -146,7 +168,7 @@ static void multiorder_check(unsigned long index, int order)
146 168
147 slot = radix_tree_lookup_slot(&tree, index); 169 slot = radix_tree_lookup_slot(&tree, index);
148 free(*slot); 170 free(*slot);
149 radix_tree_replace_slot(slot, item2); 171 radix_tree_replace_slot(&tree, slot, item2);
150 for (i = min; i < max; i++) { 172 for (i = min; i < max; i++) {
151 struct item *item = item_lookup(&tree, i); 173 struct item *item = item_lookup(&tree, i);
152 assert(item != 0); 174 assert(item != 0);
@@ -231,11 +253,14 @@ void multiorder_iteration(void)
231 radix_tree_for_each_slot(slot, &tree, &iter, j) { 253 radix_tree_for_each_slot(slot, &tree, &iter, j) {
232 int height = order[i] / RADIX_TREE_MAP_SHIFT; 254 int height = order[i] / RADIX_TREE_MAP_SHIFT;
233 int shift = height * RADIX_TREE_MAP_SHIFT; 255 int shift = height * RADIX_TREE_MAP_SHIFT;
234 int mask = (1 << order[i]) - 1; 256 unsigned long mask = (1UL << order[i]) - 1;
257 struct item *item = *slot;
235 258
236 assert(iter.index >= (index[i] &~ mask)); 259 assert((iter.index | mask) == (index[i] | mask));
237 assert(iter.index <= (index[i] | mask));
238 assert(iter.shift == shift); 260 assert(iter.shift == shift);
261 assert(!radix_tree_is_internal_node(item));
262 assert((item->index | mask) == (index[i] | mask));
263 assert(item->order == order[i]);
239 i++; 264 i++;
240 } 265 }
241 } 266 }
@@ -248,7 +273,6 @@ void multiorder_tagged_iteration(void)
248 RADIX_TREE(tree, GFP_KERNEL); 273 RADIX_TREE(tree, GFP_KERNEL);
249 struct radix_tree_iter iter; 274 struct radix_tree_iter iter;
250 void **slot; 275 void **slot;
251 unsigned long first = 0;
252 int i, j; 276 int i, j;
253 277
254 printf("Multiorder tagged iteration test\n"); 278 printf("Multiorder tagged iteration test\n");
@@ -269,7 +293,7 @@ void multiorder_tagged_iteration(void)
269 assert(radix_tree_tag_set(&tree, tag_index[i], 1)); 293 assert(radix_tree_tag_set(&tree, tag_index[i], 1));
270 294
271 for (j = 0; j < 256; j++) { 295 for (j = 0; j < 256; j++) {
272 int mask, k; 296 int k;
273 297
274 for (i = 0; i < TAG_ENTRIES; i++) { 298 for (i = 0; i < TAG_ENTRIES; i++) {
275 for (k = i; index[k] < tag_index[i]; k++) 299 for (k = i; index[k] < tag_index[i]; k++)
@@ -279,18 +303,22 @@ void multiorder_tagged_iteration(void)
279 } 303 }
280 304
281 radix_tree_for_each_tagged(slot, &tree, &iter, j, 1) { 305 radix_tree_for_each_tagged(slot, &tree, &iter, j, 1) {
306 unsigned long mask;
307 struct item *item = *slot;
282 for (k = i; index[k] < tag_index[i]; k++) 308 for (k = i; index[k] < tag_index[i]; k++)
283 ; 309 ;
284 mask = (1 << order[k]) - 1; 310 mask = (1UL << order[k]) - 1;
285 311
286 assert(iter.index >= (tag_index[i] &~ mask)); 312 assert((iter.index | mask) == (tag_index[i] | mask));
287 assert(iter.index <= (tag_index[i] | mask)); 313 assert(!radix_tree_is_internal_node(item));
314 assert((item->index | mask) == (tag_index[i] | mask));
315 assert(item->order == order[k]);
288 i++; 316 i++;
289 } 317 }
290 } 318 }
291 319
292 radix_tree_range_tag_if_tagged(&tree, &first, ~0UL, 320 assert(tag_tagged_items(&tree, NULL, 0, ~0UL, TAG_ENTRIES, 1, 2) ==
293 MT_NUM_ENTRIES, 1, 2); 321 TAG_ENTRIES);
294 322
295 for (j = 0; j < 256; j++) { 323 for (j = 0; j < 256; j++) {
296 int mask, k; 324 int mask, k;
@@ -303,19 +331,21 @@ void multiorder_tagged_iteration(void)
303 } 331 }
304 332
305 radix_tree_for_each_tagged(slot, &tree, &iter, j, 2) { 333 radix_tree_for_each_tagged(slot, &tree, &iter, j, 2) {
334 struct item *item = *slot;
306 for (k = i; index[k] < tag_index[i]; k++) 335 for (k = i; index[k] < tag_index[i]; k++)
307 ; 336 ;
308 mask = (1 << order[k]) - 1; 337 mask = (1 << order[k]) - 1;
309 338
310 assert(iter.index >= (tag_index[i] &~ mask)); 339 assert((iter.index | mask) == (tag_index[i] | mask));
311 assert(iter.index <= (tag_index[i] | mask)); 340 assert(!radix_tree_is_internal_node(item));
341 assert((item->index | mask) == (tag_index[i] | mask));
342 assert(item->order == order[k]);
312 i++; 343 i++;
313 } 344 }
314 } 345 }
315 346
316 first = 1; 347 assert(tag_tagged_items(&tree, NULL, 1, ~0UL, MT_NUM_ENTRIES * 2, 1, 0)
317 radix_tree_range_tag_if_tagged(&tree, &first, ~0UL, 348 == TAG_ENTRIES);
318 MT_NUM_ENTRIES, 1, 0);
319 i = 0; 349 i = 0;
320 radix_tree_for_each_tagged(slot, &tree, &iter, 0, 0) { 350 radix_tree_for_each_tagged(slot, &tree, &iter, 0, 0) {
321 assert(iter.index == tag_index[i]); 351 assert(iter.index == tag_index[i]);
@@ -325,6 +355,261 @@ void multiorder_tagged_iteration(void)
325 item_kill_tree(&tree); 355 item_kill_tree(&tree);
326} 356}
327 357
358static void multiorder_join1(unsigned long index,
359 unsigned order1, unsigned order2)
360{
361 unsigned long loc;
362 void *item, *item2 = item_create(index + 1, order1);
363 RADIX_TREE(tree, GFP_KERNEL);
364
365 item_insert_order(&tree, index, order2);
366 item = radix_tree_lookup(&tree, index);
367 radix_tree_join(&tree, index + 1, order1, item2);
368 loc = find_item(&tree, item);
369 if (loc == -1)
370 free(item);
371 item = radix_tree_lookup(&tree, index + 1);
372 assert(item == item2);
373 item_kill_tree(&tree);
374}
375
376static void multiorder_join2(unsigned order1, unsigned order2)
377{
378 RADIX_TREE(tree, GFP_KERNEL);
379 struct radix_tree_node *node;
380 void *item1 = item_create(0, order1);
381 void *item2;
382
383 item_insert_order(&tree, 0, order2);
384 radix_tree_insert(&tree, 1 << order2, (void *)0x12UL);
385 item2 = __radix_tree_lookup(&tree, 1 << order2, &node, NULL);
386 assert(item2 == (void *)0x12UL);
387 assert(node->exceptional == 1);
388
389 radix_tree_join(&tree, 0, order1, item1);
390 item2 = __radix_tree_lookup(&tree, 1 << order2, &node, NULL);
391 assert(item2 == item1);
392 assert(node->exceptional == 0);
393 item_kill_tree(&tree);
394}
395
396/*
397 * This test revealed an accounting bug for exceptional entries at one point.
398 * Nodes were being freed back into the pool with an elevated exception count
399 * by radix_tree_join() and then radix_tree_split() was failing to zero the
400 * count of exceptional entries.
401 */
402static void multiorder_join3(unsigned int order)
403{
404 RADIX_TREE(tree, GFP_KERNEL);
405 struct radix_tree_node *node;
406 void **slot;
407 struct radix_tree_iter iter;
408 unsigned long i;
409
410 for (i = 0; i < (1 << order); i++) {
411 radix_tree_insert(&tree, i, (void *)0x12UL);
412 }
413
414 radix_tree_join(&tree, 0, order, (void *)0x16UL);
415 rcu_barrier();
416
417 radix_tree_split(&tree, 0, 0);
418
419 radix_tree_for_each_slot(slot, &tree, &iter, 0) {
420 radix_tree_iter_replace(&tree, &iter, slot, (void *)0x12UL);
421 }
422
423 __radix_tree_lookup(&tree, 0, &node, NULL);
424 assert(node->exceptional == node->count);
425
426 item_kill_tree(&tree);
427}
428
429static void multiorder_join(void)
430{
431 int i, j, idx;
432
433 for (idx = 0; idx < 1024; idx = idx * 2 + 3) {
434 for (i = 1; i < 15; i++) {
435 for (j = 0; j < i; j++) {
436 multiorder_join1(idx, i, j);
437 }
438 }
439 }
440
441 for (i = 1; i < 15; i++) {
442 for (j = 0; j < i; j++) {
443 multiorder_join2(i, j);
444 }
445 }
446
447 for (i = 3; i < 10; i++) {
448 multiorder_join3(i);
449 }
450}
451
452static void check_mem(unsigned old_order, unsigned new_order, unsigned alloc)
453{
454 struct radix_tree_preload *rtp = &radix_tree_preloads;
455 if (rtp->nr != 0)
456 printf("split(%u %u) remaining %u\n", old_order, new_order,
457 rtp->nr);
458 /*
459 * Can't check for equality here as some nodes may have been
460 * RCU-freed while we ran. But we should never finish with more
461 * nodes allocated since they should have all been preloaded.
462 */
463 if (nr_allocated > alloc)
464 printf("split(%u %u) allocated %u %u\n", old_order, new_order,
465 alloc, nr_allocated);
466}
467
468static void __multiorder_split(int old_order, int new_order)
469{
470 RADIX_TREE(tree, GFP_ATOMIC);
471 void **slot;
472 struct radix_tree_iter iter;
473 unsigned alloc;
474
475 radix_tree_preload(GFP_KERNEL);
476 assert(item_insert_order(&tree, 0, old_order) == 0);
477 radix_tree_preload_end();
478
479 /* Wipe out the preloaded cache or it'll confuse check_mem() */
480 radix_tree_cpu_dead(0);
481
482 radix_tree_tag_set(&tree, 0, 2);
483
484 radix_tree_split_preload(old_order, new_order, GFP_KERNEL);
485 alloc = nr_allocated;
486 radix_tree_split(&tree, 0, new_order);
487 check_mem(old_order, new_order, alloc);
488 radix_tree_for_each_slot(slot, &tree, &iter, 0) {
489 radix_tree_iter_replace(&tree, &iter, slot,
490 item_create(iter.index, new_order));
491 }
492 radix_tree_preload_end();
493
494 item_kill_tree(&tree);
495}
496
497static void __multiorder_split2(int old_order, int new_order)
498{
499 RADIX_TREE(tree, GFP_KERNEL);
500 void **slot;
501 struct radix_tree_iter iter;
502 struct radix_tree_node *node;
503 void *item;
504
505 __radix_tree_insert(&tree, 0, old_order, (void *)0x12);
506
507 item = __radix_tree_lookup(&tree, 0, &node, NULL);
508 assert(item == (void *)0x12);
509 assert(node->exceptional > 0);
510
511 radix_tree_split(&tree, 0, new_order);
512 radix_tree_for_each_slot(slot, &tree, &iter, 0) {
513 radix_tree_iter_replace(&tree, &iter, slot,
514 item_create(iter.index, new_order));
515 }
516
517 item = __radix_tree_lookup(&tree, 0, &node, NULL);
518 assert(item != (void *)0x12);
519 assert(node->exceptional == 0);
520
521 item_kill_tree(&tree);
522}
523
524static void __multiorder_split3(int old_order, int new_order)
525{
526 RADIX_TREE(tree, GFP_KERNEL);
527 void **slot;
528 struct radix_tree_iter iter;
529 struct radix_tree_node *node;
530 void *item;
531
532 __radix_tree_insert(&tree, 0, old_order, (void *)0x12);
533
534 item = __radix_tree_lookup(&tree, 0, &node, NULL);
535 assert(item == (void *)0x12);
536 assert(node->exceptional > 0);
537
538 radix_tree_split(&tree, 0, new_order);
539 radix_tree_for_each_slot(slot, &tree, &iter, 0) {
540 radix_tree_iter_replace(&tree, &iter, slot, (void *)0x16);
541 }
542
543 item = __radix_tree_lookup(&tree, 0, &node, NULL);
544 assert(item == (void *)0x16);
545 assert(node->exceptional > 0);
546
547 item_kill_tree(&tree);
548
549 __radix_tree_insert(&tree, 0, old_order, (void *)0x12);
550
551 item = __radix_tree_lookup(&tree, 0, &node, NULL);
552 assert(item == (void *)0x12);
553 assert(node->exceptional > 0);
554
555 radix_tree_split(&tree, 0, new_order);
556 radix_tree_for_each_slot(slot, &tree, &iter, 0) {
557 if (iter.index == (1 << new_order))
558 radix_tree_iter_replace(&tree, &iter, slot,
559 (void *)0x16);
560 else
561 radix_tree_iter_replace(&tree, &iter, slot, NULL);
562 }
563
564 item = __radix_tree_lookup(&tree, 1 << new_order, &node, NULL);
565 assert(item == (void *)0x16);
566 assert(node->count == node->exceptional);
567 do {
568 node = node->parent;
569 if (!node)
570 break;
571 assert(node->count == 1);
572 assert(node->exceptional == 0);
573 } while (1);
574
575 item_kill_tree(&tree);
576}
577
578static void multiorder_split(void)
579{
580 int i, j;
581
582 for (i = 3; i < 11; i++)
583 for (j = 0; j < i; j++) {
584 __multiorder_split(i, j);
585 __multiorder_split2(i, j);
586 __multiorder_split3(i, j);
587 }
588}
589
590static void multiorder_account(void)
591{
592 RADIX_TREE(tree, GFP_KERNEL);
593 struct radix_tree_node *node;
594 void **slot;
595
596 item_insert_order(&tree, 0, 5);
597
598 __radix_tree_insert(&tree, 1 << 5, 5, (void *)0x12);
599 __radix_tree_lookup(&tree, 0, &node, NULL);
600 assert(node->count == node->exceptional * 2);
601 radix_tree_delete(&tree, 1 << 5);
602 assert(node->exceptional == 0);
603
604 __radix_tree_insert(&tree, 1 << 5, 5, (void *)0x12);
605 __radix_tree_lookup(&tree, 1 << 5, &node, &slot);
606 assert(node->count == node->exceptional * 2);
607 __radix_tree_replace(&tree, node, slot, NULL, NULL, NULL);
608 assert(node->exceptional == 0);
609
610 item_kill_tree(&tree);
611}
612
328void multiorder_checks(void) 613void multiorder_checks(void)
329{ 614{
330 int i; 615 int i;
@@ -342,4 +627,9 @@ void multiorder_checks(void)
342 multiorder_tag_tests(); 627 multiorder_tag_tests();
343 multiorder_iteration(); 628 multiorder_iteration();
344 multiorder_tagged_iteration(); 629 multiorder_tagged_iteration();
630 multiorder_join();
631 multiorder_split();
632 multiorder_account();
633
634 radix_tree_cpu_dead(0);
345} 635}
diff --git a/tools/testing/radix-tree/rcupdate.c b/tools/testing/radix-tree/rcupdate.c
deleted file mode 100644
index 31a2d14225d6..000000000000
--- a/tools/testing/radix-tree/rcupdate.c
+++ /dev/null
@@ -1,86 +0,0 @@
1#include <linux/rcupdate.h>
2#include <pthread.h>
3#include <stdio.h>
4#include <assert.h>
5
6static pthread_mutex_t rculock = PTHREAD_MUTEX_INITIALIZER;
7static struct rcu_head *rcuhead_global = NULL;
8static __thread int nr_rcuhead = 0;
9static __thread struct rcu_head *rcuhead = NULL;
10static __thread struct rcu_head *rcutail = NULL;
11
12static pthread_cond_t rcu_worker_cond = PTHREAD_COND_INITIALIZER;
13
14/* switch to urcu implementation when it is merged. */
15void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *head))
16{
17 head->func = func;
18 head->next = rcuhead;
19 rcuhead = head;
20 if (!rcutail)
21 rcutail = head;
22 nr_rcuhead++;
23 if (nr_rcuhead >= 1000) {
24 int signal = 0;
25
26 pthread_mutex_lock(&rculock);
27 if (!rcuhead_global)
28 signal = 1;
29 rcutail->next = rcuhead_global;
30 rcuhead_global = head;
31 pthread_mutex_unlock(&rculock);
32
33 nr_rcuhead = 0;
34 rcuhead = NULL;
35 rcutail = NULL;
36
37 if (signal) {
38 pthread_cond_signal(&rcu_worker_cond);
39 }
40 }
41}
42
43static void *rcu_worker(void *arg)
44{
45 struct rcu_head *r;
46
47 rcupdate_thread_init();
48
49 while (1) {
50 pthread_mutex_lock(&rculock);
51 while (!rcuhead_global) {
52 pthread_cond_wait(&rcu_worker_cond, &rculock);
53 }
54 r = rcuhead_global;
55 rcuhead_global = NULL;
56
57 pthread_mutex_unlock(&rculock);
58
59 synchronize_rcu();
60
61 while (r) {
62 struct rcu_head *tmp = r->next;
63 r->func(r);
64 r = tmp;
65 }
66 }
67
68 rcupdate_thread_exit();
69
70 return NULL;
71}
72
73static pthread_t worker_thread;
74void rcupdate_init(void)
75{
76 pthread_create(&worker_thread, NULL, rcu_worker, NULL);
77}
78
79void rcupdate_thread_init(void)
80{
81 rcu_register_thread();
82}
83void rcupdate_thread_exit(void)
84{
85 rcu_unregister_thread();
86}
diff --git a/tools/testing/radix-tree/regression2.c b/tools/testing/radix-tree/regression2.c
index 63bf347aaf33..a41325d7a170 100644
--- a/tools/testing/radix-tree/regression2.c
+++ b/tools/testing/radix-tree/regression2.c
@@ -50,6 +50,7 @@
50#include <stdio.h> 50#include <stdio.h>
51 51
52#include "regression.h" 52#include "regression.h"
53#include "test.h"
53 54
54#define PAGECACHE_TAG_DIRTY 0 55#define PAGECACHE_TAG_DIRTY 0
55#define PAGECACHE_TAG_WRITEBACK 1 56#define PAGECACHE_TAG_WRITEBACK 1
@@ -90,7 +91,7 @@ void regression2_test(void)
90 /* 1. */ 91 /* 1. */
91 start = 0; 92 start = 0;
92 end = max_slots - 2; 93 end = max_slots - 2;
93 radix_tree_range_tag_if_tagged(&mt_tree, &start, end, 1, 94 tag_tagged_items(&mt_tree, NULL, start, end, 1,
94 PAGECACHE_TAG_DIRTY, PAGECACHE_TAG_TOWRITE); 95 PAGECACHE_TAG_DIRTY, PAGECACHE_TAG_TOWRITE);
95 96
96 /* 2. */ 97 /* 2. */
diff --git a/tools/testing/radix-tree/regression3.c b/tools/testing/radix-tree/regression3.c
index 1f06ed73d0a8..b594841fae85 100644
--- a/tools/testing/radix-tree/regression3.c
+++ b/tools/testing/radix-tree/regression3.c
@@ -5,7 +5,7 @@
5 * In following radix_tree_next_slot current chunk size becomes zero. 5 * In following radix_tree_next_slot current chunk size becomes zero.
6 * This isn't checked and it tries to dereference null pointer in slot. 6 * This isn't checked and it tries to dereference null pointer in slot.
7 * 7 *
8 * Helper radix_tree_iter_next reset slot to NULL and next_index to index + 1, 8 * Helper radix_tree_iter_resume reset slot to NULL and next_index to index + 1,
9 * for tagger iteraction it also must reset cached tags in iterator to abort 9 * for tagger iteraction it also must reset cached tags in iterator to abort
10 * next radix_tree_next_slot and go to slow-path into radix_tree_next_chunk. 10 * next radix_tree_next_slot and go to slow-path into radix_tree_next_chunk.
11 * 11 *
@@ -88,7 +88,7 @@ void regression3_test(void)
88 printf("slot %ld %p\n", iter.index, *slot); 88 printf("slot %ld %p\n", iter.index, *slot);
89 if (!iter.index) { 89 if (!iter.index) {
90 printf("next at %ld\n", iter.index); 90 printf("next at %ld\n", iter.index);
91 slot = radix_tree_iter_next(&iter); 91 slot = radix_tree_iter_resume(slot, &iter);
92 } 92 }
93 } 93 }
94 94
@@ -96,7 +96,7 @@ void regression3_test(void)
96 printf("contig %ld %p\n", iter.index, *slot); 96 printf("contig %ld %p\n", iter.index, *slot);
97 if (!iter.index) { 97 if (!iter.index) {
98 printf("next at %ld\n", iter.index); 98 printf("next at %ld\n", iter.index);
99 slot = radix_tree_iter_next(&iter); 99 slot = radix_tree_iter_resume(slot, &iter);
100 } 100 }
101 } 101 }
102 102
@@ -106,7 +106,7 @@ void regression3_test(void)
106 printf("tagged %ld %p\n", iter.index, *slot); 106 printf("tagged %ld %p\n", iter.index, *slot);
107 if (!iter.index) { 107 if (!iter.index) {
108 printf("next at %ld\n", iter.index); 108 printf("next at %ld\n", iter.index);
109 slot = radix_tree_iter_next(&iter); 109 slot = radix_tree_iter_resume(slot, &iter);
110 } 110 }
111 } 111 }
112 112
diff --git a/tools/testing/radix-tree/tag_check.c b/tools/testing/radix-tree/tag_check.c
index b0ac05741750..fd98c132207a 100644
--- a/tools/testing/radix-tree/tag_check.c
+++ b/tools/testing/radix-tree/tag_check.c
@@ -23,7 +23,7 @@ __simple_checks(struct radix_tree_root *tree, unsigned long index, int tag)
23 item_tag_set(tree, index, tag); 23 item_tag_set(tree, index, tag);
24 ret = item_tag_get(tree, index, tag); 24 ret = item_tag_get(tree, index, tag);
25 assert(ret != 0); 25 assert(ret != 0);
26 ret = radix_tree_range_tag_if_tagged(tree, &first, ~0UL, 10, tag, !tag); 26 ret = tag_tagged_items(tree, NULL, first, ~0UL, 10, tag, !tag);
27 assert(ret == 1); 27 assert(ret == 1);
28 ret = item_tag_get(tree, index, !tag); 28 ret = item_tag_get(tree, index, !tag);
29 assert(ret != 0); 29 assert(ret != 0);
@@ -51,6 +51,7 @@ void simple_checks(void)
51 verify_tag_consistency(&tree, 1); 51 verify_tag_consistency(&tree, 1);
52 printf("before item_kill_tree: %d allocated\n", nr_allocated); 52 printf("before item_kill_tree: %d allocated\n", nr_allocated);
53 item_kill_tree(&tree); 53 item_kill_tree(&tree);
54 rcu_barrier();
54 printf("after item_kill_tree: %d allocated\n", nr_allocated); 55 printf("after item_kill_tree: %d allocated\n", nr_allocated);
55} 56}
56 57
@@ -319,10 +320,13 @@ static void single_check(void)
319 assert(ret == 0); 320 assert(ret == 0);
320 verify_tag_consistency(&tree, 0); 321 verify_tag_consistency(&tree, 0);
321 verify_tag_consistency(&tree, 1); 322 verify_tag_consistency(&tree, 1);
322 ret = radix_tree_range_tag_if_tagged(&tree, &first, 10, 10, 0, 1); 323 ret = tag_tagged_items(&tree, NULL, first, 10, 10, 0, 1);
323 assert(ret == 1); 324 assert(ret == 1);
324 ret = radix_tree_gang_lookup_tag(&tree, (void **)items, 0, BATCH, 1); 325 ret = radix_tree_gang_lookup_tag(&tree, (void **)items, 0, BATCH, 1);
325 assert(ret == 1); 326 assert(ret == 1);
327 item_tag_clear(&tree, 0, 0);
328 ret = radix_tree_gang_lookup_tag(&tree, (void **)items, 0, BATCH, 0);
329 assert(ret == 0);
326 item_kill_tree(&tree); 330 item_kill_tree(&tree);
327} 331}
328 332
@@ -331,12 +335,16 @@ void tag_check(void)
331 single_check(); 335 single_check();
332 extend_checks(); 336 extend_checks();
333 contract_checks(); 337 contract_checks();
338 rcu_barrier();
334 printf("after extend_checks: %d allocated\n", nr_allocated); 339 printf("after extend_checks: %d allocated\n", nr_allocated);
335 __leak_check(); 340 __leak_check();
336 leak_check(); 341 leak_check();
342 rcu_barrier();
337 printf("after leak_check: %d allocated\n", nr_allocated); 343 printf("after leak_check: %d allocated\n", nr_allocated);
338 simple_checks(); 344 simple_checks();
345 rcu_barrier();
339 printf("after simple_checks: %d allocated\n", nr_allocated); 346 printf("after simple_checks: %d allocated\n", nr_allocated);
340 thrash_tags(); 347 thrash_tags();
348 rcu_barrier();
341 printf("after thrash_tags: %d allocated\n", nr_allocated); 349 printf("after thrash_tags: %d allocated\n", nr_allocated);
342} 350}
diff --git a/tools/testing/radix-tree/test.c b/tools/testing/radix-tree/test.c
index a6e8099eaf4f..e5726e373646 100644
--- a/tools/testing/radix-tree/test.c
+++ b/tools/testing/radix-tree/test.c
@@ -24,21 +24,29 @@ 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)
29{ 28{
30 return __radix_tree_insert(root, item->index, order, item); 29 return __radix_tree_insert(root, item->index, item->order, item);
31} 30}
32 31
33int item_insert(struct radix_tree_root *root, unsigned long index) 32int item_insert(struct radix_tree_root *root, unsigned long index)
34{ 33{
35 return __item_insert(root, item_create(index), 0); 34 return __item_insert(root, item_create(index, 0));
36} 35}
37 36
38int item_insert_order(struct radix_tree_root *root, unsigned long index, 37int item_insert_order(struct radix_tree_root *root, unsigned long index,
39 unsigned order) 38 unsigned order)
40{ 39{
41 return __item_insert(root, item_create(index), order); 40 return __item_insert(root, item_create(index, order));
41}
42
43void item_sanity(struct item *item, unsigned long index)
44{
45 unsigned long mask;
46 assert(!radix_tree_is_internal_node(item));
47 assert(item->order < BITS_PER_LONG);
48 mask = (1UL << item->order) - 1;
49 assert((item->index | mask) == (index | mask));
42} 50}
43 51
44int item_delete(struct radix_tree_root *root, unsigned long index) 52int item_delete(struct radix_tree_root *root, unsigned long index)
@@ -46,18 +54,19 @@ int item_delete(struct radix_tree_root *root, unsigned long index)
46 struct item *item = radix_tree_delete(root, index); 54 struct item *item = radix_tree_delete(root, index);
47 55
48 if (item) { 56 if (item) {
49 assert(item->index == index); 57 item_sanity(item, index);
50 free(item); 58 free(item);
51 return 1; 59 return 1;
52 } 60 }
53 return 0; 61 return 0;
54} 62}
55 63
56struct item *item_create(unsigned long index) 64struct item *item_create(unsigned long index, unsigned int order)
57{ 65{
58 struct item *ret = malloc(sizeof(*ret)); 66 struct item *ret = malloc(sizeof(*ret));
59 67
60 ret->index = index; 68 ret->index = index;
69 ret->order = order;
61 return ret; 70 return ret;
62} 71}
63 72
@@ -66,8 +75,8 @@ void item_check_present(struct radix_tree_root *root, unsigned long index)
66 struct item *item; 75 struct item *item;
67 76
68 item = radix_tree_lookup(root, index); 77 item = radix_tree_lookup(root, index);
69 assert(item != 0); 78 assert(item != NULL);
70 assert(item->index == index); 79 item_sanity(item, index);
71} 80}
72 81
73struct item *item_lookup(struct radix_tree_root *root, unsigned long index) 82struct item *item_lookup(struct radix_tree_root *root, unsigned long index)
@@ -80,7 +89,7 @@ void item_check_absent(struct radix_tree_root *root, unsigned long index)
80 struct item *item; 89 struct item *item;
81 90
82 item = radix_tree_lookup(root, index); 91 item = radix_tree_lookup(root, index);
83 assert(item == 0); 92 assert(item == NULL);
84} 93}
85 94
86/* 95/*
@@ -142,6 +151,62 @@ void item_full_scan(struct radix_tree_root *root, unsigned long start,
142 assert(nfound == 0); 151 assert(nfound == 0);
143} 152}
144 153
154/* Use the same pattern as tag_pages_for_writeback() in mm/page-writeback.c */
155int tag_tagged_items(struct radix_tree_root *root, pthread_mutex_t *lock,
156 unsigned long start, unsigned long end, unsigned batch,
157 unsigned iftag, unsigned thentag)
158{
159 unsigned long tagged = 0;
160 struct radix_tree_iter iter;
161 void **slot;
162
163 if (batch == 0)
164 batch = 1;
165
166 if (lock)
167 pthread_mutex_lock(lock);
168 radix_tree_for_each_tagged(slot, root, &iter, start, iftag) {
169 if (iter.index > end)
170 break;
171 radix_tree_iter_tag_set(root, &iter, thentag);
172 tagged++;
173 if ((tagged % batch) != 0)
174 continue;
175 slot = radix_tree_iter_resume(slot, &iter);
176 if (lock) {
177 pthread_mutex_unlock(lock);
178 rcu_barrier();
179 pthread_mutex_lock(lock);
180 }
181 }
182 if (lock)
183 pthread_mutex_unlock(lock);
184
185 return tagged;
186}
187
188/* Use the same pattern as find_swap_entry() in mm/shmem.c */
189unsigned long find_item(struct radix_tree_root *root, void *item)
190{
191 struct radix_tree_iter iter;
192 void **slot;
193 unsigned long found = -1;
194 unsigned long checked = 0;
195
196 radix_tree_for_each_slot(slot, root, &iter, 0) {
197 if (*slot == item) {
198 found = iter.index;
199 break;
200 }
201 checked++;
202 if ((checked % 4) != 0)
203 continue;
204 slot = radix_tree_iter_resume(slot, &iter);
205 }
206
207 return found;
208}
209
145static int verify_node(struct radix_tree_node *slot, unsigned int tag, 210static int verify_node(struct radix_tree_node *slot, unsigned int tag,
146 int tagged) 211 int tagged)
147{ 212{
@@ -200,9 +265,16 @@ void verify_tag_consistency(struct radix_tree_root *root, unsigned int tag)
200 265
201void item_kill_tree(struct radix_tree_root *root) 266void item_kill_tree(struct radix_tree_root *root)
202{ 267{
268 struct radix_tree_iter iter;
269 void **slot;
203 struct item *items[32]; 270 struct item *items[32];
204 int nfound; 271 int nfound;
205 272
273 radix_tree_for_each_slot(slot, root, &iter, 0) {
274 if (radix_tree_exceptional_entry(*slot))
275 radix_tree_delete(root, iter.index);
276 }
277
206 while ((nfound = radix_tree_gang_lookup(root, (void **)items, 0, 32))) { 278 while ((nfound = radix_tree_gang_lookup(root, (void **)items, 0, 32))) {
207 int i; 279 int i;
208 280
diff --git a/tools/testing/radix-tree/test.h b/tools/testing/radix-tree/test.h
index 217fb2403f09..056a23b56467 100644
--- a/tools/testing/radix-tree/test.h
+++ b/tools/testing/radix-tree/test.h
@@ -5,11 +5,11 @@
5 5
6struct item { 6struct item {
7 unsigned long index; 7 unsigned long index;
8 unsigned int order;
8}; 9};
9 10
10struct item *item_create(unsigned long index); 11struct item *item_create(unsigned long index, unsigned int order);
11int __item_insert(struct radix_tree_root *root, struct item *item, 12int __item_insert(struct radix_tree_root *root, struct item *item);
12 unsigned order);
13int 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, 14int item_insert_order(struct radix_tree_root *root, unsigned long index,
15 unsigned order); 15 unsigned order);
@@ -25,9 +25,15 @@ void item_full_scan(struct radix_tree_root *root, unsigned long start,
25 unsigned long nr, int chunk); 25 unsigned long nr, int chunk);
26void item_kill_tree(struct radix_tree_root *root); 26void item_kill_tree(struct radix_tree_root *root);
27 27
28int tag_tagged_items(struct radix_tree_root *, pthread_mutex_t *,
29 unsigned long start, unsigned long end, unsigned batch,
30 unsigned iftag, unsigned thentag);
31unsigned long find_item(struct radix_tree_root *, void *item);
32
28void tag_check(void); 33void tag_check(void);
29void multiorder_checks(void); 34void multiorder_checks(void);
30void iteration_test(void); 35void iteration_test(unsigned order, unsigned duration);
36void benchmark(void);
31 37
32struct item * 38struct item *
33item_tag_set(struct radix_tree_root *root, unsigned long index, int tag); 39item_tag_set(struct radix_tree_root *root, unsigned long index, int tag);
@@ -40,7 +46,14 @@ void verify_tag_consistency(struct radix_tree_root *root, unsigned int tag);
40extern int nr_allocated; 46extern int nr_allocated;
41 47
42/* Normally private parts of lib/radix-tree.c */ 48/* Normally private parts of lib/radix-tree.c */
49struct radix_tree_node *entry_to_node(void *ptr);
43void radix_tree_dump(struct radix_tree_root *root); 50void radix_tree_dump(struct radix_tree_root *root);
44int root_tag_get(struct radix_tree_root *root, unsigned int tag); 51int root_tag_get(struct radix_tree_root *root, unsigned int tag);
45unsigned long node_maxindex(struct radix_tree_node *); 52unsigned long node_maxindex(struct radix_tree_node *);
46unsigned long shift_maxindex(unsigned int shift); 53unsigned long shift_maxindex(unsigned int shift);
54int radix_tree_cpu_dead(unsigned int cpu);
55struct radix_tree_preload {
56 unsigned nr;
57 struct radix_tree_node *nodes;
58};
59extern struct radix_tree_preload radix_tree_preloads;
diff --git a/tools/testing/selftests/.gitignore b/tools/testing/selftests/.gitignore
new file mode 100644
index 000000000000..f0600d20ce7d
--- /dev/null
+++ b/tools/testing/selftests/.gitignore
@@ -0,0 +1 @@
kselftest
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index a3144a3de3a8..71b05891a6a1 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -7,6 +7,7 @@ TARGETS += exec
7TARGETS += firmware 7TARGETS += firmware
8TARGETS += ftrace 8TARGETS += ftrace
9TARGETS += futex 9TARGETS += futex
10TARGETS += gpio
10TARGETS += ipc 11TARGETS += ipc
11TARGETS += kcmp 12TARGETS += kcmp
12TARGETS += lib 13TARGETS += lib
@@ -24,6 +25,7 @@ TARGETS += seccomp
24TARGETS += sigaltstack 25TARGETS += sigaltstack
25TARGETS += size 26TARGETS += size
26TARGETS += static_keys 27TARGETS += static_keys
28TARGETS += sync
27TARGETS += sysctl 29TARGETS += sysctl
28ifneq (1, $(quicktest)) 30ifneq (1, $(quicktest))
29TARGETS += timers 31TARGETS += timers
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 0103bf2e0c0d..853d7e43434a 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -1059,7 +1059,7 @@ static struct bpf_test tests[] = {
1059 BPF_MOV64_IMM(BPF_REG_0, 0), 1059 BPF_MOV64_IMM(BPF_REG_0, 0),
1060 BPF_EXIT_INSN(), 1060 BPF_EXIT_INSN(),
1061 }, 1061 },
1062 .errstr_unpriv = "unknown func 6", 1062 .errstr_unpriv = "unknown func bpf_trace_printk#6",
1063 .result_unpriv = REJECT, 1063 .result_unpriv = REJECT,
1064 .result = ACCEPT, 1064 .result = ACCEPT,
1065 }, 1065 },
@@ -2661,6 +2661,34 @@ static struct bpf_test tests[] = {
2661 .prog_type = BPF_PROG_TYPE_SCHED_CLS 2661 .prog_type = BPF_PROG_TYPE_SCHED_CLS
2662 }, 2662 },
2663 { 2663 {
2664 "multiple registers share map_lookup_elem bad reg type",
2665 .insns = {
2666 BPF_MOV64_IMM(BPF_REG_1, 10),
2667 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
2668 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
2669 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
2670 BPF_LD_MAP_FD(BPF_REG_1, 0),
2671 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
2672 BPF_FUNC_map_lookup_elem),
2673 BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
2674 BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
2675 BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
2676 BPF_MOV64_REG(BPF_REG_5, BPF_REG_0),
2677 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
2678 BPF_MOV64_IMM(BPF_REG_1, 1),
2679 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
2680 BPF_MOV64_IMM(BPF_REG_1, 2),
2681 BPF_JMP_IMM(BPF_JEQ, BPF_REG_3, 0, 1),
2682 BPF_ST_MEM(BPF_DW, BPF_REG_3, 0, 0),
2683 BPF_MOV64_IMM(BPF_REG_1, 3),
2684 BPF_EXIT_INSN(),
2685 },
2686 .fixup_map1 = { 4 },
2687 .result = REJECT,
2688 .errstr = "R3 invalid mem access 'inv'",
2689 .prog_type = BPF_PROG_TYPE_SCHED_CLS
2690 },
2691 {
2664 "invalid map access from else condition", 2692 "invalid map access from else condition",
2665 .insns = { 2693 .insns = {
2666 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 2694 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
diff --git a/tools/testing/selftests/breakpoints/Makefile b/tools/testing/selftests/breakpoints/Makefile
index 74e533fd4bc5..61b79e8df1f4 100644
--- a/tools/testing/selftests/breakpoints/Makefile
+++ b/tools/testing/selftests/breakpoints/Makefile
@@ -5,6 +5,9 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
5ifeq ($(ARCH),x86) 5ifeq ($(ARCH),x86)
6TEST_PROGS := breakpoint_test 6TEST_PROGS := breakpoint_test
7endif 7endif
8ifeq ($(ARCH),aarch64)
9TEST_PROGS := breakpoint_test_arm64
10endif
8 11
9TEST_PROGS += step_after_suspend_test 12TEST_PROGS += step_after_suspend_test
10 13
@@ -13,4 +16,4 @@ all: $(TEST_PROGS)
13include ../lib.mk 16include ../lib.mk
14 17
15clean: 18clean:
16 rm -fr breakpoint_test step_after_suspend_test 19 rm -fr breakpoint_test breakpoint_test_arm64 step_after_suspend_test
diff --git a/tools/testing/selftests/breakpoints/breakpoint_test_arm64.c b/tools/testing/selftests/breakpoints/breakpoint_test_arm64.c
new file mode 100644
index 000000000000..3897e996541e
--- /dev/null
+++ b/tools/testing/selftests/breakpoints/breakpoint_test_arm64.c
@@ -0,0 +1,236 @@
1/*
2 * Copyright (C) 2016 Google, Inc.
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * Original Code by Pavel Labath <labath@google.com>
14 *
15 * Code modified by Pratyush Anand <panand@redhat.com>
16 * for testing different byte select for each access size.
17 *
18 */
19
20#define _GNU_SOURCE
21
22#include <sys/types.h>
23#include <sys/wait.h>
24#include <sys/ptrace.h>
25#include <sys/param.h>
26#include <sys/uio.h>
27#include <stdint.h>
28#include <stdbool.h>
29#include <stddef.h>
30#include <string.h>
31#include <stdio.h>
32#include <unistd.h>
33#include <elf.h>
34#include <errno.h>
35#include <signal.h>
36
37#include "../kselftest.h"
38
39static volatile uint8_t var[96] __attribute__((__aligned__(32)));
40
41static void child(int size, int wr)
42{
43 volatile uint8_t *addr = &var[32 + wr];
44
45 if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) != 0) {
46 perror("ptrace(PTRACE_TRACEME) failed");
47 _exit(1);
48 }
49
50 if (raise(SIGSTOP) != 0) {
51 perror("raise(SIGSTOP) failed");
52 _exit(1);
53 }
54
55 if ((uintptr_t) addr % size) {
56 perror("Wrong address write for the given size\n");
57 _exit(1);
58 }
59 switch (size) {
60 case 1:
61 *addr = 47;
62 break;
63 case 2:
64 *(uint16_t *)addr = 47;
65 break;
66 case 4:
67 *(uint32_t *)addr = 47;
68 break;
69 case 8:
70 *(uint64_t *)addr = 47;
71 break;
72 case 16:
73 __asm__ volatile ("stp x29, x30, %0" : "=m" (addr[0]));
74 break;
75 case 32:
76 __asm__ volatile ("stp q29, q30, %0" : "=m" (addr[0]));
77 break;
78 }
79
80 _exit(0);
81}
82
83static bool set_watchpoint(pid_t pid, int size, int wp)
84{
85 const volatile uint8_t *addr = &var[32 + wp];
86 const int offset = (uintptr_t)addr % 8;
87 const unsigned int byte_mask = ((1 << size) - 1) << offset;
88 const unsigned int type = 2; /* Write */
89 const unsigned int enable = 1;
90 const unsigned int control = byte_mask << 5 | type << 3 | enable;
91 struct user_hwdebug_state dreg_state;
92 struct iovec iov;
93
94 memset(&dreg_state, 0, sizeof(dreg_state));
95 dreg_state.dbg_regs[0].addr = (uintptr_t)(addr - offset);
96 dreg_state.dbg_regs[0].ctrl = control;
97 iov.iov_base = &dreg_state;
98 iov.iov_len = offsetof(struct user_hwdebug_state, dbg_regs) +
99 sizeof(dreg_state.dbg_regs[0]);
100 if (ptrace(PTRACE_SETREGSET, pid, NT_ARM_HW_WATCH, &iov) == 0)
101 return true;
102
103 if (errno == EIO) {
104 printf("ptrace(PTRACE_SETREGSET, NT_ARM_HW_WATCH) "
105 "not supported on this hardware\n");
106 ksft_exit_skip();
107 }
108 perror("ptrace(PTRACE_SETREGSET, NT_ARM_HW_WATCH) failed");
109 return false;
110}
111
112static bool run_test(int wr_size, int wp_size, int wr, int wp)
113{
114 int status;
115 siginfo_t siginfo;
116 pid_t pid = fork();
117 pid_t wpid;
118
119 if (pid < 0) {
120 perror("fork() failed");
121 return false;
122 }
123 if (pid == 0)
124 child(wr_size, wr);
125
126 wpid = waitpid(pid, &status, __WALL);
127 if (wpid != pid) {
128 perror("waitpid() failed");
129 return false;
130 }
131 if (!WIFSTOPPED(status)) {
132 printf("child did not stop\n");
133 return false;
134 }
135 if (WSTOPSIG(status) != SIGSTOP) {
136 printf("child did not stop with SIGSTOP\n");
137 return false;
138 }
139
140 if (!set_watchpoint(pid, wp_size, wp))
141 return false;
142
143 if (ptrace(PTRACE_CONT, pid, NULL, NULL) < 0) {
144 perror("ptrace(PTRACE_SINGLESTEP) failed");
145 return false;
146 }
147
148 alarm(3);
149 wpid = waitpid(pid, &status, __WALL);
150 if (wpid != pid) {
151 perror("waitpid() failed");
152 return false;
153 }
154 alarm(0);
155 if (WIFEXITED(status)) {
156 printf("child did not single-step\t");
157 return false;
158 }
159 if (!WIFSTOPPED(status)) {
160 printf("child did not stop\n");
161 return false;
162 }
163 if (WSTOPSIG(status) != SIGTRAP) {
164 printf("child did not stop with SIGTRAP\n");
165 return false;
166 }
167 if (ptrace(PTRACE_GETSIGINFO, pid, NULL, &siginfo) != 0) {
168 perror("ptrace(PTRACE_GETSIGINFO)");
169 return false;
170 }
171 if (siginfo.si_code != TRAP_HWBKPT) {
172 printf("Unexpected si_code %d\n", siginfo.si_code);
173 return false;
174 }
175
176 kill(pid, SIGKILL);
177 wpid = waitpid(pid, &status, 0);
178 if (wpid != pid) {
179 perror("waitpid() failed");
180 return false;
181 }
182 return true;
183}
184
185static void sigalrm(int sig)
186{
187}
188
189int main(int argc, char **argv)
190{
191 int opt;
192 bool succeeded = true;
193 struct sigaction act;
194 int wr, wp, size;
195 bool result;
196
197 act.sa_handler = sigalrm;
198 sigemptyset(&act.sa_mask);
199 act.sa_flags = 0;
200 sigaction(SIGALRM, &act, NULL);
201 for (size = 1; size <= 32; size = size*2) {
202 for (wr = 0; wr <= 32; wr = wr + size) {
203 for (wp = wr - size; wp <= wr + size; wp = wp + size) {
204 printf("Test size = %d write offset = %d watchpoint offset = %d\t", size, wr, wp);
205 result = run_test(size, MIN(size, 8), wr, wp);
206 if ((result && wr == wp) || (!result && wr != wp)) {
207 printf("[OK]\n");
208 ksft_inc_pass_cnt();
209 } else {
210 printf("[FAILED]\n");
211 ksft_inc_fail_cnt();
212 succeeded = false;
213 }
214 }
215 }
216 }
217
218 for (size = 1; size <= 32; size = size*2) {
219 printf("Test size = %d write offset = %d watchpoint offset = -8\t", size, -size);
220
221 if (run_test(size, 8, -size, -8)) {
222 printf("[OK]\n");
223 ksft_inc_pass_cnt();
224 } else {
225 printf("[FAILED]\n");
226 ksft_inc_fail_cnt();
227 succeeded = false;
228 }
229 }
230
231 ksft_print_cnts();
232 if (succeeded)
233 ksft_exit_pass();
234 else
235 ksft_exit_fail();
236}
diff --git a/tools/testing/selftests/drivers/gpu/i915.sh b/tools/testing/selftests/drivers/gpu/i915.sh
new file mode 100755
index 000000000000..d407f0fa1e3a
--- /dev/null
+++ b/tools/testing/selftests/drivers/gpu/i915.sh
@@ -0,0 +1,14 @@
1#!/bin/sh
2# Runs hardware independent tests for i915 (drivers/gpu/drm/i915)
3
4if ! /sbin/modprobe -q -r i915; then
5 echo "drivers/gpu/i915: [SKIP]"
6 exit 77
7fi
8
9if /sbin/modprobe -q i915 mock_selftests=-1; then
10 echo "drivers/gpu/i915: ok"
11else
12 echo "drivers/gpu/i915: [FAIL]"
13 exit 1
14fi
diff --git a/tools/testing/selftests/ftrace/.gitignore b/tools/testing/selftests/ftrace/.gitignore
new file mode 100644
index 000000000000..98d8a5a63049
--- /dev/null
+++ b/tools/testing/selftests/ftrace/.gitignore
@@ -0,0 +1 @@
logs
diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
index 4c6a0bf8ba79..52e3c4df28d6 100755
--- a/tools/testing/selftests/ftrace/ftracetest
+++ b/tools/testing/selftests/ftrace/ftracetest
@@ -13,7 +13,8 @@ echo "Usage: ftracetest [options] [testcase(s)] [testcase-directory(s)]"
13echo " Options:" 13echo " Options:"
14echo " -h|--help Show help message" 14echo " -h|--help Show help message"
15echo " -k|--keep Keep passed test logs" 15echo " -k|--keep Keep passed test logs"
16echo " -v|--verbose Show all stdout messages in testcases" 16echo " -v|--verbose Increase verbosity of test messages"
17echo " -vv Alias of -v -v (Show all results in stdout)"
17echo " -d|--debug Debug mode (trace all shell commands)" 18echo " -d|--debug Debug mode (trace all shell commands)"
18exit $1 19exit $1
19} 20}
@@ -54,8 +55,9 @@ parse_opts() { # opts
54 KEEP_LOG=1 55 KEEP_LOG=1
55 shift 1 56 shift 1
56 ;; 57 ;;
57 --verbose|-v) 58 --verbose|-v|-vv)
58 VERBOSE=1 59 VERBOSE=$((VERBOSE + 1))
60 [ $1 == '-vv' ] && VERBOSE=$((VERBOSE + 1))
59 shift 1 61 shift 1
60 ;; 62 ;;
61 --debug|-d) 63 --debug|-d)
@@ -228,7 +230,7 @@ trap 'SIG_RESULT=$XFAIL' $SIG_XFAIL
228 230
229__run_test() { # testfile 231__run_test() { # testfile
230 # setup PID and PPID, $$ is not updated. 232 # setup PID and PPID, $$ is not updated.
231 (cd $TRACING_DIR; read PID _ < /proc/self/stat ; set -e; set -x; . $1) 233 (cd $TRACING_DIR; read PID _ < /proc/self/stat; set -e; set -x; initialize_ftrace; . $1)
232 [ $? -ne 0 ] && kill -s $SIG_FAIL $SIG_PID 234 [ $? -ne 0 ] && kill -s $SIG_FAIL $SIG_PID
233} 235}
234 236
@@ -236,10 +238,11 @@ __run_test() { # testfile
236run_test() { # testfile 238run_test() { # testfile
237 local testname=`basename $1` 239 local testname=`basename $1`
238 local testlog=`mktemp $LOG_DIR/${testname}-log.XXXXXX` 240 local testlog=`mktemp $LOG_DIR/${testname}-log.XXXXXX`
241 export TMPDIR=`mktemp -d /tmp/ftracetest-dir.XXXXXX`
239 testcase $1 242 testcase $1
240 echo "execute: "$1 > $testlog 243 echo "execute: "$1 > $testlog
241 SIG_RESULT=0 244 SIG_RESULT=0
242 if [ $VERBOSE -ne 0 ]; then 245 if [ $VERBOSE -ge 2 ]; then
243 __run_test $1 2>> $testlog | tee -a $testlog 246 __run_test $1 2>> $testlog | tee -a $testlog
244 else 247 else
245 __run_test $1 >> $testlog 2>&1 248 __run_test $1 >> $testlog 2>&1
@@ -249,9 +252,10 @@ run_test() { # testfile
249 # Remove test log if the test was done as it was expected. 252 # Remove test log if the test was done as it was expected.
250 [ $KEEP_LOG -eq 0 ] && rm $testlog 253 [ $KEEP_LOG -eq 0 ] && rm $testlog
251 else 254 else
252 catlog $testlog 255 [ $VERBOSE -ge 1 ] && catlog $testlog
253 TOTAL_RESULT=1 256 TOTAL_RESULT=1
254 fi 257 fi
258 rm -rf $TMPDIR
255} 259}
256 260
257# load in the helper functions 261# load in the helper functions
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc
new file mode 100644
index 000000000000..9dcd0ca1f49c
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc
@@ -0,0 +1,49 @@
1#!/bin/sh
2# description: ftrace - function glob filters
3
4# Make sure that function glob matching filter works.
5
6if ! grep -q function available_tracers; then
7 echo "no function tracer configured"
8 exit_unsupported
9fi
10
11disable_tracing
12clear_trace
13
14# filter by ?, schedule is always good
15if ! echo "sch?dule" > set_ftrace_filter; then
16 # test for powerpc 64
17 if ! echo ".sch?dule" > set_ftrace_filter; then
18 fail "can not enable schedule filter"
19 fi
20 cat set_ftrace_filter | grep '^.schedule$'
21else
22 cat set_ftrace_filter | grep '^schedule$'
23fi
24
25ftrace_filter_check() { # glob grep
26 echo "$1" > set_ftrace_filter
27 cut -f1 -d" " set_ftrace_filter > $TMPDIR/actual
28 cut -f1 -d" " available_filter_functions | grep "$2" > $TMPDIR/expected
29 DIFF=`diff $TMPDIR/actual $TMPDIR/expected`
30 test -z "$DIFF"
31}
32
33# filter by *, front match
34ftrace_filter_check '*schedule' '^.*schedule$'
35
36# filter by *, middle match
37ftrace_filter_check '*schedule*' '^.*schedule.*$'
38
39# filter by *, end match
40ftrace_filter_check 'schedule*' '^schedule.*$'
41
42# filter by *, both side match
43ftrace_filter_check 'sch*ule' '^sch.*ule$'
44
45# filter by char class.
46ftrace_filter_check '[Ss]y[Ss]_*' '^[Ss]y[Ss]_.*$'
47
48echo > set_ftrace_filter
49enable_tracing
diff --git a/tools/testing/selftests/ftrace/test.d/functions b/tools/testing/selftests/ftrace/test.d/functions
index c37262f6c269..91de1a8e4f19 100644
--- a/tools/testing/selftests/ftrace/test.d/functions
+++ b/tools/testing/selftests/ftrace/test.d/functions
@@ -23,3 +23,31 @@ reset_trigger() { # reset all current setting triggers
23 done 23 done
24} 24}
25 25
26reset_events_filter() { # reset all current setting filters
27 grep -v ^none events/*/*/filter |
28 while read line; do
29 echo 0 > `echo $line | cut -f1 -d:`
30 done
31}
32
33disable_events() {
34 echo 0 > events/enable
35}
36
37initialize_ftrace() { # Reset ftrace to initial-state
38# As the initial state, ftrace will be set to nop tracer,
39# no events, no triggers, no filters, no function filters,
40# no probes, and tracing on.
41 disable_tracing
42 reset_tracer
43 reset_trigger
44 reset_events_filter
45 disable_events
46 echo > set_event_pid # event tracer is always on
47 [ -f set_ftrace_filter ] && echo | tee set_ftrace_*
48 [ -f set_graph_function ] && echo | tee set_graph_*
49 [ -f stack_trace_filter ] && echo > stack_trace_filter
50 [ -f kprobe_events ] && echo > kprobe_events
51 [ -f uprobe_events ] && echo > uprobe_events
52 enable_tracing
53}
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_type.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_type.tc
new file mode 100644
index 000000000000..0a78705b43b2
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_type.tc
@@ -0,0 +1,37 @@
1#!/bin/sh
2# description: Kprobes event arguments with types
3
4[ -f kprobe_events ] || exit_unsupported # this is configurable
5
6grep "x8/16/32/64" README > /dev/null || exit_unsupported # version issue
7
8echo 0 > events/enable
9echo > kprobe_events
10enable_tracing
11
12echo 'p:testprobe _do_fork $stack0:s32 $stack0:u32 $stack0:x32 $stack0:b8@4/32' > kprobe_events
13grep testprobe kprobe_events
14test -d events/kprobes/testprobe
15
16echo 1 > events/kprobes/testprobe/enable
17( echo "forked")
18echo 0 > events/kprobes/testprobe/enable
19ARGS=`tail -n 1 trace | sed -e 's/.* arg1=\(.*\) arg2=\(.*\) arg3=\(.*\) arg4=\(.*\)/\1 \2 \3 \4/'`
20
21check_types() {
22 X1=`printf "%x" $1 | tail -c 8`
23 X2=`printf "%x" $2`
24 X3=`printf "%x" $3`
25 test $X1 = $X2
26 test $X2 = $X3
27 test 0x$X3 = $3
28
29 B4=`printf "%x" $4`
30 B3=`echo -n $X3 | tail -c 3 | head -c 2`
31 test $B3 = $B4
32}
33check_types $ARGS
34
35echo "-:testprobe" >> kprobe_events
36clear_trace
37test -d events/kprobes/testprobe && exit 1 || exit 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
index 0bf5085281f3..400e98b64948 100644
--- a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc
@@ -56,7 +56,7 @@ echo "Test histogram with syscall modifier"
56 56
57echo 'hist:keys=id.syscall' > events/raw_syscalls/sys_exit/trigger 57echo 'hist:keys=id.syscall' > events/raw_syscalls/sys_exit/trigger
58for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done 58for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
59grep "id: sys_" events/raw_syscalls/sys_exit/hist > /dev/null || \ 59grep "id: \(unknown_\|sys_\)" events/raw_syscalls/sys_exit/hist > /dev/null || \
60 fail "syscall modifier on raw_syscalls/sys_exit did not work" 60 fail "syscall modifier on raw_syscalls/sys_exit did not work"
61 61
62 62
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc
index f84b80d551a2..ed94f0c4e0e4 100644
--- a/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc
@@ -23,6 +23,11 @@ if [ ! -f events/sched/sched_process_fork/trigger ]; then
23 exit_unsupported 23 exit_unsupported
24fi 24fi
25 25
26if [ ! -f snapshot ]; then
27 echo "snapshot is not supported"
28 exit_unsupported
29fi
30
26reset_tracer 31reset_tracer
27do_reset 32do_reset
28 33
diff --git a/tools/testing/selftests/futex/README b/tools/testing/selftests/futex/README
index 0558bb9ce0a6..f3926c33ed4c 100644
--- a/tools/testing/selftests/futex/README
+++ b/tools/testing/selftests/futex/README
@@ -59,4 +59,4 @@ o FIXME: decide on a sane test naming scheme. Currently the tests are named
59Coding Style 59Coding Style
60------------ 60------------
61o The Futex Test project adheres to the coding standards set forth by Linux 61o The Futex Test project adheres to the coding standards set forth by Linux
62 kernel as defined in the Linux source Documentation/CodingStyle. 62 kernel as defined in the Linux source Documentation/process/coding-style.rst.
diff --git a/tools/testing/selftests/gpio/Makefile b/tools/testing/selftests/gpio/Makefile
new file mode 100644
index 000000000000..205e4d10e085
--- /dev/null
+++ b/tools/testing/selftests/gpio/Makefile
@@ -0,0 +1,23 @@
1
2TEST_PROGS := gpio-mockup.sh
3TEST_FILES := gpio-mockup-sysfs.sh $(BINARIES)
4BINARIES := gpio-mockup-chardev
5
6include ../lib.mk
7
8all: $(BINARIES)
9
10clean:
11 $(RM) $(BINARIES)
12
13CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/
14LDLIBS += -lmount -I/usr/include/libmount
15
16$(BINARIES): ../../../gpio/gpio-utils.o ../../../../usr/include/linux/gpio.h
17
18../../../gpio/gpio-utils.o:
19 make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C ../../../gpio
20
21../../../../usr/include/linux/gpio.h:
22 make -C ../../../.. headers_install INSTALL_HDR_PATH=$(shell pwd)/../../../../usr/
23
diff --git a/tools/testing/selftests/gpio/gpio-mockup-chardev.c b/tools/testing/selftests/gpio/gpio-mockup-chardev.c
new file mode 100644
index 000000000000..667e916fa7cc
--- /dev/null
+++ b/tools/testing/selftests/gpio/gpio-mockup-chardev.c
@@ -0,0 +1,324 @@
1/*
2 * GPIO chardev test helper
3 *
4 * Copyright (C) 2016 Bamvor Jian Zhang
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 */
10
11#define _GNU_SOURCE
12#include <unistd.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <stdio.h>
16#include <errno.h>
17#include <string.h>
18#include <fcntl.h>
19#include <getopt.h>
20#include <sys/ioctl.h>
21#include <libmount.h>
22#include <err.h>
23#include <dirent.h>
24#include <linux/gpio.h>
25#include "../../../gpio/gpio-utils.h"
26
27#define CONSUMER "gpio-selftest"
28#define GC_NUM 10
29enum direction {
30 OUT,
31 IN
32};
33
34static int get_debugfs(char **path)
35{
36 struct libmnt_context *cxt;
37 struct libmnt_table *tb;
38 struct libmnt_iter *itr = NULL;
39 struct libmnt_fs *fs;
40 int found = 0;
41
42 cxt = mnt_new_context();
43 if (!cxt)
44 err(EXIT_FAILURE, "libmount context allocation failed");
45
46 itr = mnt_new_iter(MNT_ITER_FORWARD);
47 if (!itr)
48 err(EXIT_FAILURE, "failed to initialize libmount iterator");
49
50 if (mnt_context_get_mtab(cxt, &tb))
51 err(EXIT_FAILURE, "failed to read mtab");
52
53 while (mnt_table_next_fs(tb, itr, &fs) == 0) {
54 const char *type = mnt_fs_get_fstype(fs);
55
56 if (!strcmp(type, "debugfs")) {
57 found = 1;
58 break;
59 }
60 }
61 if (found)
62 asprintf(path, "%s/gpio", mnt_fs_get_target(fs));
63
64 mnt_free_iter(itr);
65 mnt_free_context(cxt);
66
67 if (!found)
68 return -1;
69
70 return 0;
71}
72
73static int gpio_debugfs_get(const char *consumer, int *dir, int *value)
74{
75 char *debugfs;
76 FILE *f;
77 char *line = NULL;
78 size_t len = 0;
79 char *cur;
80 int found = 0;
81
82 if (get_debugfs(&debugfs) != 0)
83 err(EXIT_FAILURE, "debugfs is not mounted");
84
85 f = fopen(debugfs, "r");
86 if (!f)
87 err(EXIT_FAILURE, "read from gpio debugfs failed");
88
89 /*
90 * gpio-2 ( |gpio-selftest ) in lo
91 */
92 while (getline(&line, &len, f) != -1) {
93 cur = strstr(line, consumer);
94 if (cur == NULL)
95 continue;
96
97 cur = strchr(line, ')');
98 if (!cur)
99 continue;
100
101 cur += 2;
102 if (!strncmp(cur, "out", 3)) {
103 *dir = OUT;
104 cur += 4;
105 } else if (!strncmp(cur, "in", 2)) {
106 *dir = IN;
107 cur += 4;
108 }
109
110 if (!strncmp(cur, "hi", 2))
111 *value = 1;
112 else if (!strncmp(cur, "lo", 2))
113 *value = 0;
114
115 found = 1;
116 break;
117 }
118 free(debugfs);
119 fclose(f);
120 free(line);
121
122 if (!found)
123 return -1;
124
125 return 0;
126}
127
128static struct gpiochip_info *list_gpiochip(const char *gpiochip_name, int *ret)
129{
130 struct gpiochip_info *cinfo;
131 struct gpiochip_info *current;
132 const struct dirent *ent;
133 DIR *dp;
134 char *chrdev_name;
135 int fd;
136 int i = 0;
137
138 cinfo = calloc(sizeof(struct gpiochip_info) * 4, GC_NUM + 1);
139 if (!cinfo)
140 err(EXIT_FAILURE, "gpiochip_info allocation failed");
141
142 current = cinfo;
143 dp = opendir("/dev");
144 if (!dp) {
145 *ret = -errno;
146 goto error_out;
147 } else {
148 *ret = 0;
149 }
150
151 while (ent = readdir(dp), ent) {
152 if (check_prefix(ent->d_name, "gpiochip")) {
153 *ret = asprintf(&chrdev_name, "/dev/%s", ent->d_name);
154 if (*ret < 0)
155 goto error_out;
156
157 fd = open(chrdev_name, 0);
158 if (fd == -1) {
159 *ret = -errno;
160 fprintf(stderr, "Failed to open %s\n",
161 chrdev_name);
162 goto error_close_dir;
163 }
164 *ret = ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, current);
165 if (*ret == -1) {
166 perror("Failed to issue CHIPINFO IOCTL\n");
167 goto error_close_dir;
168 }
169 close(fd);
170 if (strcmp(current->label, gpiochip_name) == 0
171 || check_prefix(current->label, gpiochip_name)) {
172 *ret = 0;
173 current++;
174 i++;
175 }
176 }
177 }
178
179 if ((!*ret && i == 0) || *ret < 0) {
180 free(cinfo);
181 cinfo = NULL;
182 }
183 if (!*ret && i > 0) {
184 cinfo = realloc(cinfo, sizeof(struct gpiochip_info) * 4 * i);
185 *ret = i;
186 }
187
188error_close_dir:
189 closedir(dp);
190error_out:
191 if (*ret < 0)
192 err(EXIT_FAILURE, "list gpiochip failed: %s", strerror(*ret));
193
194 return cinfo;
195}
196
197int gpio_pin_test(struct gpiochip_info *cinfo, int line, int flag, int value)
198{
199 struct gpiohandle_data data;
200 unsigned int lines[] = {line};
201 int fd;
202 int debugfs_dir = IN;
203 int debugfs_value = 0;
204 int ret;
205
206 data.values[0] = value;
207 ret = gpiotools_request_linehandle(cinfo->name, lines, 1, flag, &data,
208 CONSUMER);
209 if (ret < 0)
210 goto fail_out;
211 else
212 fd = ret;
213
214 ret = gpio_debugfs_get(CONSUMER, &debugfs_dir, &debugfs_value);
215 if (ret) {
216 ret = -EINVAL;
217 goto fail_out;
218 }
219 if (flag & GPIOHANDLE_REQUEST_INPUT) {
220 if (debugfs_dir != IN) {
221 errno = -EINVAL;
222 ret = -errno;
223 }
224 } else if (flag & GPIOHANDLE_REQUEST_OUTPUT) {
225 if (flag & GPIOHANDLE_REQUEST_ACTIVE_LOW)
226 debugfs_value = !debugfs_value;
227
228 if (!(debugfs_dir == OUT && value == debugfs_value))
229 errno = -EINVAL;
230 ret = -errno;
231
232 }
233 gpiotools_release_linehandle(fd);
234
235fail_out:
236 if (ret)
237 err(EXIT_FAILURE, "gpio<%s> line<%d> test flag<0x%x> value<%d>",
238 cinfo->name, line, flag, value);
239
240 return ret;
241}
242
243void gpio_pin_tests(struct gpiochip_info *cinfo, unsigned int line)
244{
245 printf("line<%d>", line);
246 gpio_pin_test(cinfo, line, GPIOHANDLE_REQUEST_OUTPUT, 0);
247 printf(".");
248 gpio_pin_test(cinfo, line, GPIOHANDLE_REQUEST_OUTPUT, 1);
249 printf(".");
250 gpio_pin_test(cinfo, line,
251 GPIOHANDLE_REQUEST_OUTPUT | GPIOHANDLE_REQUEST_ACTIVE_LOW,
252 0);
253 printf(".");
254 gpio_pin_test(cinfo, line,
255 GPIOHANDLE_REQUEST_OUTPUT | GPIOHANDLE_REQUEST_ACTIVE_LOW,
256 1);
257 printf(".");
258 gpio_pin_test(cinfo, line, GPIOHANDLE_REQUEST_INPUT, 0);
259 printf(".");
260}
261
262/*
263 * ./gpio-mockup-chardev gpio_chip_name_prefix is_valid_gpio_chip
264 * Return 0 if successful or exit with EXIT_FAILURE if test failed.
265 * gpio_chip_name_prefix: The prefix of gpiochip you want to test. E.g.
266 * gpio-mockup
267 * is_valid_gpio_chip: Whether the gpio_chip is valid. 1 means valid,
268 * 0 means invalid which could not be found by
269 * list_gpiochip.
270 */
271int main(int argc, char *argv[])
272{
273 char *prefix;
274 int valid;
275 struct gpiochip_info *cinfo;
276 struct gpiochip_info *current;
277 int i;
278 int ret;
279
280 if (argc < 3) {
281 printf("Usage: %s prefix is_valid", argv[0]);
282 exit(EXIT_FAILURE);
283 }
284
285 prefix = argv[1];
286 valid = strcmp(argv[2], "true") == 0 ? 1 : 0;
287
288 printf("Test gpiochip %s: ", prefix);
289 cinfo = list_gpiochip(prefix, &ret);
290 if (!cinfo) {
291 if (!valid && ret == 0) {
292 printf("Invalid test successful\n");
293 ret = 0;
294 goto out;
295 } else {
296 ret = -EINVAL;
297 goto out;
298 }
299 } else if (cinfo && !valid) {
300 ret = -EINVAL;
301 goto out;
302 }
303 current = cinfo;
304 for (i = 0; i < ret; i++) {
305 gpio_pin_tests(current, 0);
306 gpio_pin_tests(current, current->lines - 1);
307 gpio_pin_tests(current, random() % current->lines);
308 current++;
309 }
310 ret = 0;
311 printf("successful\n");
312
313out:
314 if (ret)
315 fprintf(stderr, "gpio<%s> test failed\n", prefix);
316
317 if (cinfo)
318 free(cinfo);
319
320 if (ret)
321 exit(EXIT_FAILURE);
322
323 return ret;
324}
diff --git a/tools/testing/selftests/gpio/gpio-mockup-sysfs.sh b/tools/testing/selftests/gpio/gpio-mockup-sysfs.sh
new file mode 100755
index 000000000000..085d7a39899c
--- /dev/null
+++ b/tools/testing/selftests/gpio/gpio-mockup-sysfs.sh
@@ -0,0 +1,134 @@
1
2is_consistent()
3{
4 val=
5
6 active_low_sysfs=`cat $GPIO_SYSFS/gpio$nr/active_low`
7 val_sysfs=`cat $GPIO_SYSFS/gpio$nr/value`
8 dir_sysfs=`cat $GPIO_SYSFS/gpio$nr/direction`
9
10 gpio_this_debugfs=`cat $GPIO_DEBUGFS |grep "gpio-$nr" | sed "s/(.*)//g"`
11 dir_debugfs=`echo $gpio_this_debugfs | awk '{print $2}'`
12 val_debugfs=`echo $gpio_this_debugfs | awk '{print $3}'`
13 if [ $val_debugfs = "lo" ]; then
14 val=0
15 elif [ $val_debugfs = "hi" ]; then
16 val=1
17 fi
18
19 if [ $active_low_sysfs = "1" ]; then
20 if [ $val = "0" ]; then
21 val="1"
22 else
23 val="0"
24 fi
25 fi
26
27 if [ $val_sysfs = $val ] && [ $dir_sysfs = $dir_debugfs ]; then
28 echo -n "."
29 else
30 echo "test fail, exit"
31 die
32 fi
33}
34
35test_pin_logic()
36{
37 nr=$1
38 direction=$2
39 active_low=$3
40 value=$4
41
42 echo $direction > $GPIO_SYSFS/gpio$nr/direction
43 echo $active_low > $GPIO_SYSFS/gpio$nr/active_low
44 if [ $direction = "out" ]; then
45 echo $value > $GPIO_SYSFS/gpio$nr/value
46 fi
47 is_consistent $nr
48}
49
50test_one_pin()
51{
52 nr=$1
53
54 echo -n "test pin<$nr>"
55
56 echo $nr > $GPIO_SYSFS/export 2>/dev/null
57
58 if [ X$? != X0 ]; then
59 echo "test GPIO pin $nr failed"
60 die
61 fi
62
63 #"Checking if the sysfs is consistent with debugfs: "
64 is_consistent $nr
65
66 #"Checking the logic of active_low: "
67 test_pin_logic $nr out 1 1
68 test_pin_logic $nr out 1 0
69 test_pin_logic $nr out 0 1
70 test_pin_logic $nr out 0 0
71
72 #"Checking the logic of direction: "
73 test_pin_logic $nr in 1 1
74 test_pin_logic $nr out 1 0
75 test_pin_logic $nr low 0 1
76 test_pin_logic $nr high 0 0
77
78 echo $nr > $GPIO_SYSFS/unexport
79
80 echo "successful"
81}
82
83test_one_pin_fail()
84{
85 nr=$1
86
87 echo $nr > $GPIO_SYSFS/export 2>/dev/null
88
89 if [ X$? != X0 ]; then
90 echo "test invalid pin $nr successful"
91 else
92 echo "test invalid pin $nr failed"
93 echo $nr > $GPIO_SYSFS/unexport 2>/dev/null
94 die
95 fi
96}
97
98list_chip()
99{
100 echo `ls -d $GPIO_DRV_SYSFS/gpiochip* 2>/dev/null`
101}
102
103test_chip()
104{
105 chip=$1
106 name=`basename $chip`
107 base=`cat $chip/base`
108 ngpio=`cat $chip/ngpio`
109 printf "%-10s %-5s %-5s\n" $name $base $ngpio
110 if [ $ngpio = "0" ]; then
111 echo "number of gpio is zero is not allowed".
112 fi
113 test_one_pin $base
114 test_one_pin $(($base + $ngpio - 1))
115 test_one_pin $((( RANDOM % $ngpio ) + $base ))
116}
117
118test_chips_sysfs()
119{
120 gpiochip=`list_chip $module`
121 if [ X"$gpiochip" = X ]; then
122 if [ X"$valid" = Xfalse ]; then
123 echo "successful"
124 else
125 echo "fail"
126 die
127 fi
128 else
129 for chip in $gpiochip; do
130 test_chip $chip
131 done
132 fi
133}
134
diff --git a/tools/testing/selftests/gpio/gpio-mockup.sh b/tools/testing/selftests/gpio/gpio-mockup.sh
new file mode 100755
index 000000000000..b183439e058e
--- /dev/null
+++ b/tools/testing/selftests/gpio/gpio-mockup.sh
@@ -0,0 +1,201 @@
1#!/bin/bash
2
3#exit status
4#1: run as non-root user
5#2: sysfs/debugfs not mount
6#3: insert module fail when gpio-mockup is a module.
7#4: other reason.
8
9SYSFS=
10GPIO_SYSFS=
11GPIO_DRV_SYSFS=
12DEBUGFS=
13GPIO_DEBUGFS=
14dev_type=
15module=
16
17usage()
18{
19 echo "Usage:"
20 echo "$0 [-f] [-m name] [-t type]"
21 echo "-f: full test. It maybe conflict with existence gpio device."
22 echo "-m: module name, default name is gpio-mockup. It could also test"
23 echo " other gpio device."
24 echo "-t: interface type: chardev(char device) and sysfs(being"
25 echo " deprecated). The first one is default"
26 echo ""
27 echo "$0 -h"
28 echo "This usage"
29}
30
31prerequisite()
32{
33 msg="skip all tests:"
34 if [ $UID != 0 ]; then
35 echo $msg must be run as root >&2
36 exit 1
37 fi
38 SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'`
39 if [ ! -d "$SYSFS" ]; then
40 echo $msg sysfs is not mounted >&2
41 exit 2
42 fi
43 GPIO_SYSFS=`echo $SYSFS/class/gpio`
44 GPIO_DRV_SYSFS=`echo $SYSFS/devices/platform/$module/gpio`
45 DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'`
46 if [ ! -d "$DEBUGFS" ]; then
47 echo $msg debugfs is not mounted >&2
48 exit 2
49 fi
50 GPIO_DEBUGFS=`echo $DEBUGFS/gpio`
51 source gpio-mockup-sysfs.sh
52}
53
54try_insert_module()
55{
56 if [ -d "$GPIO_DRV_SYSFS" ]; then
57 echo "$GPIO_DRV_SYSFS exist. Skip insert module"
58 else
59 modprobe -q $module $1
60 if [ X$? != X0 ]; then
61 echo $msg insmod $module failed >&2
62 exit 3
63 fi
64 fi
65}
66
67remove_module()
68{
69 modprobe -r -q $module
70}
71
72die()
73{
74 remove_module
75 exit 4
76}
77
78test_chips()
79{
80 if [ X$dev_type = Xsysfs ]; then
81 echo "WARNING: sysfs ABI of gpio is going to deprecated."
82 test_chips_sysfs $*
83 else
84 $BASE/gpio-mockup-chardev $*
85 fi
86}
87
88gpio_test()
89{
90 param=$1
91 valid=$2
92
93 if [ X"$param" = X ]; then
94 die
95 fi
96 try_insert_module "gpio_mockup_ranges=$param"
97 echo -n "GPIO $module test with ranges: <"
98 echo "$param>: "
99 printf "%-10s %s\n" $param
100 test_chips $module $valid
101 remove_module
102}
103
104BASE=`dirname $0`
105
106dev_type=
107TEMP=`getopt -o fhm:t: -n '$0' -- "$@"`
108
109if [ "$?" != "0" ]; then
110 echo "Parameter process failed, Terminating..." >&2
111 exit 1
112fi
113
114# Note the quotes around `$TEMP': they are essential!
115eval set -- "$TEMP"
116
117while true; do
118 case $1 in
119 -f)
120 full_test=true
121 shift
122 ;;
123 -h)
124 usage
125 exit
126 ;;
127 -m)
128 module=$2
129 shift 2
130 ;;
131 -t)
132 dev_type=$2
133 shift 2
134 ;;
135 --)
136 shift
137 break
138 ;;
139 *)
140 echo "Internal error!"
141 exit 1
142 ;;
143 esac
144done
145
146if [ X"$module" = X ]; then
147 module="gpio-mockup"
148fi
149
150if [ X$dev_type != Xsysfs ]; then
151 dev_type="chardev"
152fi
153
154prerequisite
155
156echo "1. Test dynamic allocation of gpio successful means insert gpiochip and"
157echo " manipulate gpio pin successful"
158gpio_test "-1,32" true
159gpio_test "-1,32,-1,32" true
160gpio_test "-1,32,-1,32,-1,32" true
161if [ X$full_test = Xtrue ]; then
162 gpio_test "-1,32,32,64" true
163 gpio_test "-1,32,40,64,-1,5" true
164 gpio_test "-1,32,32,64,-1,32" true
165 gpio_test "0,32,32,64,-1,32,-1,32" true
166 gpio_test "-1,32,-1,32,0,32,32,64" true
167 echo "2. Do basic test: successful means insert gpiochip and"
168 echo " manipulate gpio pin successful"
169 gpio_test "0,32" true
170 gpio_test "0,32,32,64" true
171 gpio_test "0,32,40,64,64,96" true
172fi
173echo "3. Error test: successful means insert gpiochip failed"
174echo "3.1 Test number of gpio overflow"
175#Currently: The max number of gpio(1024) is defined in arm architecture.
176gpio_test "-1,32,-1,1024" false
177if [ X$full_test = Xtrue ]; then
178 echo "3.2 Test zero line of gpio"
179 gpio_test "0,0" false
180 echo "3.3 Test range overlap"
181 echo "3.3.1 Test corner case"
182 gpio_test "0,32,0,1" false
183 gpio_test "0,32,32,64,32,40" false
184 gpio_test "0,32,35,64,35,45" false
185 gpio_test "0,32,31,32" false
186 gpio_test "0,32,32,64,36,37" false
187 gpio_test "0,32,35,64,34,36" false
188 echo "3.3.2 Test inserting invalid second gpiochip"
189 gpio_test "0,32,30,35" false
190 gpio_test "0,32,1,5" false
191 gpio_test "10,32,9,14" false
192 gpio_test "10,32,30,35" false
193 echo "3.3.3 Test others"
194 gpio_test "0,32,40,56,39,45" false
195 gpio_test "0,32,40,56,30,33" false
196 gpio_test "0,32,40,56,30,41" false
197 gpio_test "0,32,40,56,20,21" false
198fi
199
200echo GPIO test PASS
201
diff --git a/tools/testing/selftests/nsfs/.gitignore b/tools/testing/selftests/nsfs/.gitignore
new file mode 100644
index 000000000000..2ab2c824ce86
--- /dev/null
+++ b/tools/testing/selftests/nsfs/.gitignore
@@ -0,0 +1,2 @@
1owner
2pidns
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
index db54a33f850f..c2c4211ba58b 100644
--- a/tools/testing/selftests/powerpc/Makefile
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -8,7 +8,7 @@ ifeq ($(ARCH),powerpc)
8 8
9GIT_VERSION = $(shell git describe --always --long --dirty || echo "unknown") 9GIT_VERSION = $(shell git describe --always --long --dirty || echo "unknown")
10 10
11CFLAGS := -std=gnu99 -Wall -O2 -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR) $(CFLAGS) 11CFLAGS := -std=gnu99 -Wall -O2 -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR)/include $(CFLAGS)
12 12
13export CFLAGS 13export CFLAGS
14 14
@@ -26,7 +26,8 @@ SUB_DIRS = alignment \
26 syscalls \ 26 syscalls \
27 tm \ 27 tm \
28 vphn \ 28 vphn \
29 math 29 math \
30 ptrace
30 31
31endif 32endif
32 33
diff --git a/tools/testing/selftests/powerpc/benchmarks/.gitignore b/tools/testing/selftests/powerpc/benchmarks/.gitignore
index bce49ebd869e..04dc1e6ef2ce 100644
--- a/tools/testing/selftests/powerpc/benchmarks/.gitignore
+++ b/tools/testing/selftests/powerpc/benchmarks/.gitignore
@@ -1,4 +1,5 @@
1gettimeofday 1gettimeofday
2context_switch 2context_switch
3mmap_bench 3mmap_bench
4futex_bench \ No newline at end of file 4futex_bench
5null_syscall
diff --git a/tools/testing/selftests/powerpc/benchmarks/Makefile b/tools/testing/selftests/powerpc/benchmarks/Makefile
index a9adfb7de78f..545077f98f72 100644
--- a/tools/testing/selftests/powerpc/benchmarks/Makefile
+++ b/tools/testing/selftests/powerpc/benchmarks/Makefile
@@ -1,4 +1,4 @@
1TEST_PROGS := gettimeofday context_switch mmap_bench futex_bench 1TEST_PROGS := gettimeofday context_switch mmap_bench futex_bench null_syscall
2 2
3CFLAGS += -O2 3CFLAGS += -O2
4 4
diff --git a/tools/testing/selftests/powerpc/benchmarks/context_switch.c b/tools/testing/selftests/powerpc/benchmarks/context_switch.c
index a36883ad48a4..778f5fbfd784 100644
--- a/tools/testing/selftests/powerpc/benchmarks/context_switch.c
+++ b/tools/testing/selftests/powerpc/benchmarks/context_switch.c
@@ -28,7 +28,7 @@
28#ifdef __powerpc__ 28#ifdef __powerpc__
29#include <altivec.h> 29#include <altivec.h>
30#endif 30#endif
31#include "../utils.h" 31#include "utils.h"
32 32
33static unsigned int timeout = 30; 33static unsigned int timeout = 30;
34 34
diff --git a/tools/testing/selftests/powerpc/benchmarks/null_syscall.c b/tools/testing/selftests/powerpc/benchmarks/null_syscall.c
new file mode 100644
index 000000000000..ecc14d68e101
--- /dev/null
+++ b/tools/testing/selftests/powerpc/benchmarks/null_syscall.c
@@ -0,0 +1,157 @@
1/*
2 * Test null syscall performance
3 *
4 * Copyright (C) 2009-2015 Anton Blanchard, IBM
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#define NR_LOOPS 10000000
13
14#include <string.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <unistd.h>
18#include <time.h>
19#include <sys/types.h>
20#include <sys/time.h>
21#include <signal.h>
22
23static volatile int soak_done;
24unsigned long long clock_frequency;
25unsigned long long timebase_frequency;
26double timebase_multiplier;
27
28static inline unsigned long long mftb(void)
29{
30 unsigned long low;
31
32 asm volatile("mftb %0" : "=r" (low));
33
34 return low;
35}
36
37static void sigalrm_handler(int unused)
38{
39 soak_done = 1;
40}
41
42/*
43 * Use a timer instead of busy looping on clock_gettime() so we don't
44 * pollute profiles with glibc and VDSO hits.
45 */
46static void cpu_soak_usecs(unsigned long usecs)
47{
48 struct itimerval val;
49
50 memset(&val, 0, sizeof(val));
51 val.it_value.tv_usec = usecs;
52
53 signal(SIGALRM, sigalrm_handler);
54 setitimer(ITIMER_REAL, &val, NULL);
55
56 while (1) {
57 if (soak_done)
58 break;
59 }
60
61 signal(SIGALRM, SIG_DFL);
62}
63
64/*
65 * This only works with recent kernels where cpufreq modifies
66 * /proc/cpuinfo dynamically.
67 */
68static void get_proc_frequency(void)
69{
70 FILE *f;
71 char line[128];
72 char *p, *end;
73 unsigned long v;
74 double d;
75 char *override;
76
77 /* Try to get out of low power/low frequency mode */
78 cpu_soak_usecs(0.25 * 1000000);
79
80 f = fopen("/proc/cpuinfo", "r");
81 if (f == NULL)
82 return;
83
84 timebase_frequency = 0;
85
86 while (fgets(line, sizeof(line), f) != NULL) {
87 if (strncmp(line, "timebase", 8) == 0) {
88 p = strchr(line, ':');
89 if (p != NULL) {
90 v = strtoull(p + 1, &end, 0);
91 if (end != p + 1)
92 timebase_frequency = v;
93 }
94 }
95
96 if (((strncmp(line, "clock", 5) == 0) ||
97 (strncmp(line, "cpu MHz", 7) == 0))) {
98 p = strchr(line, ':');
99 if (p != NULL) {
100 d = strtod(p + 1, &end);
101 if (end != p + 1) {
102 /* Find fastest clock frequency */
103 if ((d * 1000000ULL) > clock_frequency)
104 clock_frequency = d * 1000000ULL;
105 }
106 }
107 }
108 }
109
110 fclose(f);
111
112 override = getenv("FREQUENCY");
113 if (override)
114 clock_frequency = strtoull(override, NULL, 10);
115
116 if (timebase_frequency)
117 timebase_multiplier = (double)clock_frequency
118 / timebase_frequency;
119 else
120 timebase_multiplier = 1;
121}
122
123static void do_null_syscall(unsigned long nr)
124{
125 unsigned long i;
126
127 for (i = 0; i < nr; i++)
128 getppid();
129}
130
131#define TIME(A, STR) \
132
133int main(void)
134{
135 unsigned long tb_start, tb_now;
136 struct timespec tv_start, tv_now;
137 unsigned long long elapsed_ns, elapsed_tb;
138
139 get_proc_frequency();
140
141 clock_gettime(CLOCK_MONOTONIC, &tv_start);
142 tb_start = mftb();
143
144 do_null_syscall(NR_LOOPS);
145
146 clock_gettime(CLOCK_MONOTONIC, &tv_now);
147 tb_now = mftb();
148
149 elapsed_ns = (tv_now.tv_sec - tv_start.tv_sec) * 1000000000ULL +
150 (tv_now.tv_nsec - tv_start.tv_nsec);
151 elapsed_tb = tb_now - tb_start;
152
153 printf("%10.2f ns %10.2f cycles\n", (float)elapsed_ns / NR_LOOPS,
154 (float)elapsed_tb * timebase_multiplier / NR_LOOPS);
155
156 return 0;
157}
diff --git a/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h b/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h
index 50ae7d2091ce..80d34a9ffff4 100644
--- a/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h
+++ b/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h
@@ -25,6 +25,8 @@
25 25
26#define PPC_MTOCRF(A, B) mtocrf A, B 26#define PPC_MTOCRF(A, B) mtocrf A, B
27 27
28#define EX_TABLE(x, y)
29
28FUNC_START(enter_vmx_usercopy) 30FUNC_START(enter_vmx_usercopy)
29 li r3,1 31 li r3,1
30 blr 32 blr
diff --git a/tools/testing/selftests/powerpc/copyloops/validate.c b/tools/testing/selftests/powerpc/copyloops/validate.c
index 1750ff57ee58..7fb436f82d16 100644
--- a/tools/testing/selftests/powerpc/copyloops/validate.c
+++ b/tools/testing/selftests/powerpc/copyloops/validate.c
@@ -3,7 +3,7 @@
3#include <stdlib.h> 3#include <stdlib.h>
4#include <stdbool.h> 4#include <stdbool.h>
5 5
6#include "../utils.h" 6#include "utils.h"
7 7
8#define MAX_LEN 8192 8#define MAX_LEN 8192
9#define MAX_OFFSET 16 9#define MAX_OFFSET 16
diff --git a/tools/testing/selftests/powerpc/dscr/dscr.h b/tools/testing/selftests/powerpc/dscr/dscr.h
index a36af1b2c2bb..18ea223bd398 100644
--- a/tools/testing/selftests/powerpc/dscr/dscr.h
+++ b/tools/testing/selftests/powerpc/dscr/dscr.h
@@ -28,8 +28,6 @@
28 28
29#include "utils.h" 29#include "utils.h"
30 30
31#define SPRN_DSCR 0x11 /* Privilege state SPR */
32#define SPRN_DSCR_USR 0x03 /* Problem state SPR */
33#define THREADS 100 /* Max threads */ 31#define THREADS 100 /* Max threads */
34#define COUNT 100 /* Max iterations */ 32#define COUNT 100 /* Max iterations */
35#define DSCR_MAX 16 /* Max DSCR value */ 33#define DSCR_MAX 16 /* Max DSCR value */
@@ -48,14 +46,14 @@ inline unsigned long get_dscr(void)
48{ 46{
49 unsigned long ret; 47 unsigned long ret;
50 48
51 asm volatile("mfspr %0,%1" : "=r" (ret): "i" (SPRN_DSCR)); 49 asm volatile("mfspr %0,%1" : "=r" (ret) : "i" (SPRN_DSCR_PRIV));
52 50
53 return ret; 51 return ret;
54} 52}
55 53
56inline void set_dscr(unsigned long val) 54inline void set_dscr(unsigned long val)
57{ 55{
58 asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR)); 56 asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR_PRIV));
59} 57}
60 58
61/* Problem state DSCR access */ 59/* Problem state DSCR access */
@@ -63,14 +61,14 @@ inline unsigned long get_dscr_usr(void)
63{ 61{
64 unsigned long ret; 62 unsigned long ret;
65 63
66 asm volatile("mfspr %0,%1" : "=r" (ret): "i" (SPRN_DSCR_USR)); 64 asm volatile("mfspr %0,%1" : "=r" (ret) : "i" (SPRN_DSCR));
67 65
68 return ret; 66 return ret;
69} 67}
70 68
71inline void set_dscr_usr(unsigned long val) 69inline void set_dscr_usr(unsigned long val)
72{ 70{
73 asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR_USR)); 71 asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR));
74} 72}
75 73
76/* Default DSCR access */ 74/* Default DSCR access */
diff --git a/tools/testing/selftests/powerpc/basic_asm.h b/tools/testing/selftests/powerpc/include/basic_asm.h
index 3349a0704d1a..12eaddf72e66 100644
--- a/tools/testing/selftests/powerpc/basic_asm.h
+++ b/tools/testing/selftests/powerpc/include/basic_asm.h
@@ -4,12 +4,12 @@
4#include <ppc-asm.h> 4#include <ppc-asm.h>
5#include <asm/unistd.h> 5#include <asm/unistd.h>
6 6
7#define LOAD_REG_IMMEDIATE(reg,expr) \ 7#define LOAD_REG_IMMEDIATE(reg, expr) \
8 lis reg,(expr)@highest; \ 8 lis reg, (expr)@highest; \
9 ori reg,reg,(expr)@higher; \ 9 ori reg, reg, (expr)@higher; \
10 rldicr reg,reg,32,31; \ 10 rldicr reg, reg, 32, 31; \
11 oris reg,reg,(expr)@high; \ 11 oris reg, reg, (expr)@high; \
12 ori reg,reg,(expr)@l; 12 ori reg, reg, (expr)@l;
13 13
14/* 14/*
15 * Note: These macros assume that variables being stored on the stack are 15 * Note: These macros assume that variables being stored on the stack are
@@ -20,7 +20,8 @@
20#define STACK_FRAME_MIN_SIZE 32 20#define STACK_FRAME_MIN_SIZE 32
21#define STACK_FRAME_TOC_POS 24 21#define STACK_FRAME_TOC_POS 24
22#define __STACK_FRAME_PARAM(_param) (32 + ((_param)*8)) 22#define __STACK_FRAME_PARAM(_param) (32 + ((_param)*8))
23#define __STACK_FRAME_LOCAL(_num_params,_var_num) ((STACK_FRAME_PARAM(_num_params)) + ((_var_num)*8)) 23#define __STACK_FRAME_LOCAL(_num_params, _var_num) \
24 ((STACK_FRAME_PARAM(_num_params)) + ((_var_num)*8))
24#else 25#else
25#define STACK_FRAME_MIN_SIZE 112 26#define STACK_FRAME_MIN_SIZE 112
26#define STACK_FRAME_TOC_POS 40 27#define STACK_FRAME_TOC_POS 40
@@ -30,14 +31,16 @@
30 * Caveat: if a function passed more than 8 doublewords, the caller will have 31 * Caveat: if a function passed more than 8 doublewords, the caller will have
31 * made more space... which would render the 112 incorrect. 32 * made more space... which would render the 112 incorrect.
32 */ 33 */
33#define __STACK_FRAME_LOCAL(_num_params,_var_num) (112 + ((_var_num)*8)) 34#define __STACK_FRAME_LOCAL(_num_params, _var_num) \
35 (112 + ((_var_num)*8))
34#endif 36#endif
35 37
36/* Parameter x saved to the stack */ 38/* Parameter x saved to the stack */
37#define STACK_FRAME_PARAM(var) __STACK_FRAME_PARAM(var) 39#define STACK_FRAME_PARAM(var) __STACK_FRAME_PARAM(var)
38 40
39/* Local variable x saved to the stack after x parameters */ 41/* Local variable x saved to the stack after x parameters */
40#define STACK_FRAME_LOCAL(num_params,var) __STACK_FRAME_LOCAL(num_params,var) 42#define STACK_FRAME_LOCAL(num_params, var) \
43 __STACK_FRAME_LOCAL(num_params, var)
41#define STACK_FRAME_LR_POS 16 44#define STACK_FRAME_LR_POS 16
42#define STACK_FRAME_CR_POS 8 45#define STACK_FRAME_CR_POS 8
43 46
@@ -53,18 +56,18 @@
53 */ 56 */
54#define PUSH_BASIC_STACK(_extra) \ 57#define PUSH_BASIC_STACK(_extra) \
55 mflr r0; \ 58 mflr r0; \
56 std r0,STACK_FRAME_LR_POS(%r1); \ 59 std r0, STACK_FRAME_LR_POS(%r1); \
57 stdu %r1,-(_extra + STACK_FRAME_MIN_SIZE)(%r1); \ 60 stdu %r1, -(_extra + STACK_FRAME_MIN_SIZE)(%r1); \
58 mfcr r0; \ 61 mfcr r0; \
59 stw r0,STACK_FRAME_CR_POS(%r1); \ 62 stw r0, STACK_FRAME_CR_POS(%r1); \
60 std %r2,STACK_FRAME_TOC_POS(%r1); 63 std %r2, STACK_FRAME_TOC_POS(%r1);
61 64
62#define POP_BASIC_STACK(_extra) \ 65#define POP_BASIC_STACK(_extra) \
63 ld %r2,STACK_FRAME_TOC_POS(%r1); \ 66 ld %r2, STACK_FRAME_TOC_POS(%r1); \
64 lwz r0,STACK_FRAME_CR_POS(%r1); \ 67 lwz r0, STACK_FRAME_CR_POS(%r1); \
65 mtcr r0; \ 68 mtcr r0; \
66 addi %r1,%r1,(_extra + STACK_FRAME_MIN_SIZE); \ 69 addi %r1, %r1, (_extra + STACK_FRAME_MIN_SIZE); \
67 ld r0,STACK_FRAME_LR_POS(%r1); \ 70 ld r0, STACK_FRAME_LR_POS(%r1); \
68 mtlr r0; 71 mtlr r0;
69 72
70#endif /* _SELFTESTS_POWERPC_BASIC_ASM_H */ 73#endif /* _SELFTESTS_POWERPC_BASIC_ASM_H */
diff --git a/tools/testing/selftests/powerpc/fpu_asm.h b/tools/testing/selftests/powerpc/include/fpu_asm.h
index 6a387d255e27..6a387d255e27 100644
--- a/tools/testing/selftests/powerpc/fpu_asm.h
+++ b/tools/testing/selftests/powerpc/include/fpu_asm.h
diff --git a/tools/testing/selftests/powerpc/gpr_asm.h b/tools/testing/selftests/powerpc/include/gpr_asm.h
index f6f38852d3a0..f6f38852d3a0 100644
--- a/tools/testing/selftests/powerpc/gpr_asm.h
+++ b/tools/testing/selftests/powerpc/include/gpr_asm.h
diff --git a/tools/testing/selftests/powerpc/instructions.h b/tools/testing/selftests/powerpc/include/instructions.h
index 0fb0bd3b28c9..0fb0bd3b28c9 100644
--- a/tools/testing/selftests/powerpc/instructions.h
+++ b/tools/testing/selftests/powerpc/include/instructions.h
diff --git a/tools/testing/selftests/powerpc/include/reg.h b/tools/testing/selftests/powerpc/include/reg.h
new file mode 100644
index 000000000000..4afdebcce4cd
--- /dev/null
+++ b/tools/testing/selftests/powerpc/include/reg.h
@@ -0,0 +1,145 @@
1/*
2 * Copyright 2014, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#ifndef _SELFTESTS_POWERPC_REG_H
7#define _SELFTESTS_POWERPC_REG_H
8
9#define __stringify_1(x) #x
10#define __stringify(x) __stringify_1(x)
11
12#define mfspr(rn) ({unsigned long rval; \
13 asm volatile("mfspr %0," _str(rn) \
14 : "=r" (rval)); rval; })
15#define mtspr(rn, v) asm volatile("mtspr " _str(rn) ",%0" : \
16 : "r" ((unsigned long)(v)) \
17 : "memory")
18
19#define mb() asm volatile("sync" : : : "memory");
20
21#define SPRN_MMCR2 769
22#define SPRN_MMCRA 770
23#define SPRN_MMCR0 779
24#define MMCR0_PMAO 0x00000080
25#define MMCR0_PMAE 0x04000000
26#define MMCR0_FC 0x80000000
27#define SPRN_EBBHR 804
28#define SPRN_EBBRR 805
29#define SPRN_BESCR 806 /* Branch event status & control register */
30#define SPRN_BESCRS 800 /* Branch event status & control set (1 bits set to 1) */
31#define SPRN_BESCRSU 801 /* Branch event status & control set upper */
32#define SPRN_BESCRR 802 /* Branch event status & control REset (1 bits set to 0) */
33#define SPRN_BESCRRU 803 /* Branch event status & control REset upper */
34
35#define BESCR_PMEO 0x1 /* PMU Event-based exception Occurred */
36#define BESCR_PME (0x1ul << 32) /* PMU Event-based exception Enable */
37
38#define SPRN_PMC1 771
39#define SPRN_PMC2 772
40#define SPRN_PMC3 773
41#define SPRN_PMC4 774
42#define SPRN_PMC5 775
43#define SPRN_PMC6 776
44
45#define SPRN_SIAR 780
46#define SPRN_SDAR 781
47#define SPRN_SIER 768
48
49#define SPRN_TEXASR 0x82 /* Transaction Exception and Status Register */
50#define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */
51#define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */
52#define SPRN_TAR 0x32f /* Target Address Register */
53
54#define SPRN_DSCR_PRIV 0x11 /* Privilege State DSCR */
55#define SPRN_DSCR 0x03 /* Data Stream Control Register */
56#define SPRN_PPR 896 /* Program Priority Register */
57
58/* TEXASR register bits */
59#define TEXASR_FC 0xFE00000000000000
60#define TEXASR_FP 0x0100000000000000
61#define TEXASR_DA 0x0080000000000000
62#define TEXASR_NO 0x0040000000000000
63#define TEXASR_FO 0x0020000000000000
64#define TEXASR_SIC 0x0010000000000000
65#define TEXASR_NTC 0x0008000000000000
66#define TEXASR_TC 0x0004000000000000
67#define TEXASR_TIC 0x0002000000000000
68#define TEXASR_IC 0x0001000000000000
69#define TEXASR_IFC 0x0000800000000000
70#define TEXASR_ABT 0x0000000100000000
71#define TEXASR_SPD 0x0000000080000000
72#define TEXASR_HV 0x0000000020000000
73#define TEXASR_PR 0x0000000010000000
74#define TEXASR_FS 0x0000000008000000
75#define TEXASR_TE 0x0000000004000000
76#define TEXASR_ROT 0x0000000002000000
77
78/* Vector Instructions */
79#define VSX_XX1(xs, ra, rb) (((xs) & 0x1f) << 21 | ((ra) << 16) | \
80 ((rb) << 11) | (((xs) >> 5)))
81#define STXVD2X(xs, ra, rb) .long (0x7c000798 | VSX_XX1((xs), (ra), (rb)))
82#define LXVD2X(xs, ra, rb) .long (0x7c000698 | VSX_XX1((xs), (ra), (rb)))
83
84#define ASM_LOAD_GPR_IMMED(_asm_symbol_name_immed) \
85 "li 14, %[" #_asm_symbol_name_immed "];" \
86 "li 15, %[" #_asm_symbol_name_immed "];" \
87 "li 16, %[" #_asm_symbol_name_immed "];" \
88 "li 17, %[" #_asm_symbol_name_immed "];" \
89 "li 18, %[" #_asm_symbol_name_immed "];" \
90 "li 19, %[" #_asm_symbol_name_immed "];" \
91 "li 20, %[" #_asm_symbol_name_immed "];" \
92 "li 21, %[" #_asm_symbol_name_immed "];" \
93 "li 22, %[" #_asm_symbol_name_immed "];" \
94 "li 23, %[" #_asm_symbol_name_immed "];" \
95 "li 24, %[" #_asm_symbol_name_immed "];" \
96 "li 25, %[" #_asm_symbol_name_immed "];" \
97 "li 26, %[" #_asm_symbol_name_immed "];" \
98 "li 27, %[" #_asm_symbol_name_immed "];" \
99 "li 28, %[" #_asm_symbol_name_immed "];" \
100 "li 29, %[" #_asm_symbol_name_immed "];" \
101 "li 30, %[" #_asm_symbol_name_immed "];" \
102 "li 31, %[" #_asm_symbol_name_immed "];"
103
104#define ASM_LOAD_FPR_SINGLE_PRECISION(_asm_symbol_name_addr) \
105 "lfs 0, 0(%[" #_asm_symbol_name_addr "]);" \
106 "lfs 1, 0(%[" #_asm_symbol_name_addr "]);" \
107 "lfs 2, 0(%[" #_asm_symbol_name_addr "]);" \
108 "lfs 3, 0(%[" #_asm_symbol_name_addr "]);" \
109 "lfs 4, 0(%[" #_asm_symbol_name_addr "]);" \
110 "lfs 5, 0(%[" #_asm_symbol_name_addr "]);" \
111 "lfs 6, 0(%[" #_asm_symbol_name_addr "]);" \
112 "lfs 7, 0(%[" #_asm_symbol_name_addr "]);" \
113 "lfs 8, 0(%[" #_asm_symbol_name_addr "]);" \
114 "lfs 9, 0(%[" #_asm_symbol_name_addr "]);" \
115 "lfs 10, 0(%[" #_asm_symbol_name_addr "]);" \
116 "lfs 11, 0(%[" #_asm_symbol_name_addr "]);" \
117 "lfs 12, 0(%[" #_asm_symbol_name_addr "]);" \
118 "lfs 13, 0(%[" #_asm_symbol_name_addr "]);" \
119 "lfs 14, 0(%[" #_asm_symbol_name_addr "]);" \
120 "lfs 15, 0(%[" #_asm_symbol_name_addr "]);" \
121 "lfs 16, 0(%[" #_asm_symbol_name_addr "]);" \
122 "lfs 17, 0(%[" #_asm_symbol_name_addr "]);" \
123 "lfs 18, 0(%[" #_asm_symbol_name_addr "]);" \
124 "lfs 19, 0(%[" #_asm_symbol_name_addr "]);" \
125 "lfs 20, 0(%[" #_asm_symbol_name_addr "]);" \
126 "lfs 21, 0(%[" #_asm_symbol_name_addr "]);" \
127 "lfs 22, 0(%[" #_asm_symbol_name_addr "]);" \
128 "lfs 23, 0(%[" #_asm_symbol_name_addr "]);" \
129 "lfs 24, 0(%[" #_asm_symbol_name_addr "]);" \
130 "lfs 25, 0(%[" #_asm_symbol_name_addr "]);" \
131 "lfs 26, 0(%[" #_asm_symbol_name_addr "]);" \
132 "lfs 27, 0(%[" #_asm_symbol_name_addr "]);" \
133 "lfs 28, 0(%[" #_asm_symbol_name_addr "]);" \
134 "lfs 29, 0(%[" #_asm_symbol_name_addr "]);" \
135 "lfs 30, 0(%[" #_asm_symbol_name_addr "]);" \
136 "lfs 31, 0(%[" #_asm_symbol_name_addr "]);"
137
138#ifndef __ASSEMBLER__
139void store_gpr(unsigned long *addr);
140void load_gpr(unsigned long *addr);
141void load_fpr_single_precision(float *addr);
142void store_fpr_single_precision(float *addr);
143#endif /* end of __ASSEMBLER__ */
144
145#endif /* _SELFTESTS_POWERPC_REG_H */
diff --git a/tools/testing/selftests/powerpc/subunit.h b/tools/testing/selftests/powerpc/include/subunit.h
index 9c6c4e901ab6..9c6c4e901ab6 100644
--- a/tools/testing/selftests/powerpc/subunit.h
+++ b/tools/testing/selftests/powerpc/include/subunit.h
diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/include/utils.h
index 53405e8a52ab..53405e8a52ab 100644
--- a/tools/testing/selftests/powerpc/utils.h
+++ b/tools/testing/selftests/powerpc/include/utils.h
diff --git a/tools/testing/selftests/powerpc/vmx_asm.h b/tools/testing/selftests/powerpc/include/vmx_asm.h
index 2eaaeca9cf1d..2eaaeca9cf1d 100644
--- a/tools/testing/selftests/powerpc/vmx_asm.h
+++ b/tools/testing/selftests/powerpc/include/vmx_asm.h
diff --git a/tools/testing/selftests/powerpc/vsx_asm.h b/tools/testing/selftests/powerpc/include/vsx_asm.h
index d828bfb6ef2d..d828bfb6ef2d 100644
--- a/tools/testing/selftests/powerpc/vsx_asm.h
+++ b/tools/testing/selftests/powerpc/include/vsx_asm.h
diff --git a/tools/testing/selftests/powerpc/lib/reg.S b/tools/testing/selftests/powerpc/lib/reg.S
new file mode 100644
index 000000000000..0dc44f0da065
--- /dev/null
+++ b/tools/testing/selftests/powerpc/lib/reg.S
@@ -0,0 +1,397 @@
1/*
2 * test helper assembly functions
3 *
4 * Copyright (C) 2016 Simon Guo, IBM Corporation.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include <ppc-asm.h>
12#include "reg.h"
13
14
15/* Non volatile GPR - unsigned long buf[18] */
16FUNC_START(load_gpr)
17 ld 14, 0*8(3)
18 ld 15, 1*8(3)
19 ld 16, 2*8(3)
20 ld 17, 3*8(3)
21 ld 18, 4*8(3)
22 ld 19, 5*8(3)
23 ld 20, 6*8(3)
24 ld 21, 7*8(3)
25 ld 22, 8*8(3)
26 ld 23, 9*8(3)
27 ld 24, 10*8(3)
28 ld 25, 11*8(3)
29 ld 26, 12*8(3)
30 ld 27, 13*8(3)
31 ld 28, 14*8(3)
32 ld 29, 15*8(3)
33 ld 30, 16*8(3)
34 ld 31, 17*8(3)
35 blr
36FUNC_END(load_gpr)
37
38FUNC_START(store_gpr)
39 std 14, 0*8(3)
40 std 15, 1*8(3)
41 std 16, 2*8(3)
42 std 17, 3*8(3)
43 std 18, 4*8(3)
44 std 19, 5*8(3)
45 std 20, 6*8(3)
46 std 21, 7*8(3)
47 std 22, 8*8(3)
48 std 23, 9*8(3)
49 std 24, 10*8(3)
50 std 25, 11*8(3)
51 std 26, 12*8(3)
52 std 27, 13*8(3)
53 std 28, 14*8(3)
54 std 29, 15*8(3)
55 std 30, 16*8(3)
56 std 31, 17*8(3)
57 blr
58FUNC_END(store_gpr)
59
60/* Single Precision Float - float buf[32] */
61FUNC_START(load_fpr_single_precision)
62 lfs 0, 0*4(3)
63 lfs 1, 1*4(3)
64 lfs 2, 2*4(3)
65 lfs 3, 3*4(3)
66 lfs 4, 4*4(3)
67 lfs 5, 5*4(3)
68 lfs 6, 6*4(3)
69 lfs 7, 7*4(3)
70 lfs 8, 8*4(3)
71 lfs 9, 9*4(3)
72 lfs 10, 10*4(3)
73 lfs 11, 11*4(3)
74 lfs 12, 12*4(3)
75 lfs 13, 13*4(3)
76 lfs 14, 14*4(3)
77 lfs 15, 15*4(3)
78 lfs 16, 16*4(3)
79 lfs 17, 17*4(3)
80 lfs 18, 18*4(3)
81 lfs 19, 19*4(3)
82 lfs 20, 20*4(3)
83 lfs 21, 21*4(3)
84 lfs 22, 22*4(3)
85 lfs 23, 23*4(3)
86 lfs 24, 24*4(3)
87 lfs 25, 25*4(3)
88 lfs 26, 26*4(3)
89 lfs 27, 27*4(3)
90 lfs 28, 28*4(3)
91 lfs 29, 29*4(3)
92 lfs 30, 30*4(3)
93 lfs 31, 31*4(3)
94 blr
95FUNC_END(load_fpr_single_precision)
96
97/* Single Precision Float - float buf[32] */
98FUNC_START(store_fpr_single_precision)
99 stfs 0, 0*4(3)
100 stfs 1, 1*4(3)
101 stfs 2, 2*4(3)
102 stfs 3, 3*4(3)
103 stfs 4, 4*4(3)
104 stfs 5, 5*4(3)
105 stfs 6, 6*4(3)
106 stfs 7, 7*4(3)
107 stfs 8, 8*4(3)
108 stfs 9, 9*4(3)
109 stfs 10, 10*4(3)
110 stfs 11, 11*4(3)
111 stfs 12, 12*4(3)
112 stfs 13, 13*4(3)
113 stfs 14, 14*4(3)
114 stfs 15, 15*4(3)
115 stfs 16, 16*4(3)
116 stfs 17, 17*4(3)
117 stfs 18, 18*4(3)
118 stfs 19, 19*4(3)
119 stfs 20, 20*4(3)
120 stfs 21, 21*4(3)
121 stfs 22, 22*4(3)
122 stfs 23, 23*4(3)
123 stfs 24, 24*4(3)
124 stfs 25, 25*4(3)
125 stfs 26, 26*4(3)
126 stfs 27, 27*4(3)
127 stfs 28, 28*4(3)
128 stfs 29, 29*4(3)
129 stfs 30, 30*4(3)
130 stfs 31, 31*4(3)
131 blr
132FUNC_END(store_fpr_single_precision)
133
134/* VMX/VSX registers - unsigned long buf[128] */
135FUNC_START(loadvsx)
136 lis 4, 0
137 LXVD2X (0,(4),(3))
138 addi 4, 4, 16
139 LXVD2X (1,(4),(3))
140 addi 4, 4, 16
141 LXVD2X (2,(4),(3))
142 addi 4, 4, 16
143 LXVD2X (3,(4),(3))
144 addi 4, 4, 16
145 LXVD2X (4,(4),(3))
146 addi 4, 4, 16
147 LXVD2X (5,(4),(3))
148 addi 4, 4, 16
149 LXVD2X (6,(4),(3))
150 addi 4, 4, 16
151 LXVD2X (7,(4),(3))
152 addi 4, 4, 16
153 LXVD2X (8,(4),(3))
154 addi 4, 4, 16
155 LXVD2X (9,(4),(3))
156 addi 4, 4, 16
157 LXVD2X (10,(4),(3))
158 addi 4, 4, 16
159 LXVD2X (11,(4),(3))
160 addi 4, 4, 16
161 LXVD2X (12,(4),(3))
162 addi 4, 4, 16
163 LXVD2X (13,(4),(3))
164 addi 4, 4, 16
165 LXVD2X (14,(4),(3))
166 addi 4, 4, 16
167 LXVD2X (15,(4),(3))
168 addi 4, 4, 16
169 LXVD2X (16,(4),(3))
170 addi 4, 4, 16
171 LXVD2X (17,(4),(3))
172 addi 4, 4, 16
173 LXVD2X (18,(4),(3))
174 addi 4, 4, 16
175 LXVD2X (19,(4),(3))
176 addi 4, 4, 16
177 LXVD2X (20,(4),(3))
178 addi 4, 4, 16
179 LXVD2X (21,(4),(3))
180 addi 4, 4, 16
181 LXVD2X (22,(4),(3))
182 addi 4, 4, 16
183 LXVD2X (23,(4),(3))
184 addi 4, 4, 16
185 LXVD2X (24,(4),(3))
186 addi 4, 4, 16
187 LXVD2X (25,(4),(3))
188 addi 4, 4, 16
189 LXVD2X (26,(4),(3))
190 addi 4, 4, 16
191 LXVD2X (27,(4),(3))
192 addi 4, 4, 16
193 LXVD2X (28,(4),(3))
194 addi 4, 4, 16
195 LXVD2X (29,(4),(3))
196 addi 4, 4, 16
197 LXVD2X (30,(4),(3))
198 addi 4, 4, 16
199 LXVD2X (31,(4),(3))
200 addi 4, 4, 16
201 LXVD2X (32,(4),(3))
202 addi 4, 4, 16
203 LXVD2X (33,(4),(3))
204 addi 4, 4, 16
205 LXVD2X (34,(4),(3))
206 addi 4, 4, 16
207 LXVD2X (35,(4),(3))
208 addi 4, 4, 16
209 LXVD2X (36,(4),(3))
210 addi 4, 4, 16
211 LXVD2X (37,(4),(3))
212 addi 4, 4, 16
213 LXVD2X (38,(4),(3))
214 addi 4, 4, 16
215 LXVD2X (39,(4),(3))
216 addi 4, 4, 16
217 LXVD2X (40,(4),(3))
218 addi 4, 4, 16
219 LXVD2X (41,(4),(3))
220 addi 4, 4, 16
221 LXVD2X (42,(4),(3))
222 addi 4, 4, 16
223 LXVD2X (43,(4),(3))
224 addi 4, 4, 16
225 LXVD2X (44,(4),(3))
226 addi 4, 4, 16
227 LXVD2X (45,(4),(3))
228 addi 4, 4, 16
229 LXVD2X (46,(4),(3))
230 addi 4, 4, 16
231 LXVD2X (47,(4),(3))
232 addi 4, 4, 16
233 LXVD2X (48,(4),(3))
234 addi 4, 4, 16
235 LXVD2X (49,(4),(3))
236 addi 4, 4, 16
237 LXVD2X (50,(4),(3))
238 addi 4, 4, 16
239 LXVD2X (51,(4),(3))
240 addi 4, 4, 16
241 LXVD2X (52,(4),(3))
242 addi 4, 4, 16
243 LXVD2X (53,(4),(3))
244 addi 4, 4, 16
245 LXVD2X (54,(4),(3))
246 addi 4, 4, 16
247 LXVD2X (55,(4),(3))
248 addi 4, 4, 16
249 LXVD2X (56,(4),(3))
250 addi 4, 4, 16
251 LXVD2X (57,(4),(3))
252 addi 4, 4, 16
253 LXVD2X (58,(4),(3))
254 addi 4, 4, 16
255 LXVD2X (59,(4),(3))
256 addi 4, 4, 16
257 LXVD2X (60,(4),(3))
258 addi 4, 4, 16
259 LXVD2X (61,(4),(3))
260 addi 4, 4, 16
261 LXVD2X (62,(4),(3))
262 addi 4, 4, 16
263 LXVD2X (63,(4),(3))
264 blr
265FUNC_END(loadvsx)
266
267FUNC_START(storevsx)
268 lis 4, 0
269 STXVD2X (0,(4),(3))
270 addi 4, 4, 16
271 STXVD2X (1,(4),(3))
272 addi 4, 4, 16
273 STXVD2X (2,(4),(3))
274 addi 4, 4, 16
275 STXVD2X (3,(4),(3))
276 addi 4, 4, 16
277 STXVD2X (4,(4),(3))
278 addi 4, 4, 16
279 STXVD2X (5,(4),(3))
280 addi 4, 4, 16
281 STXVD2X (6,(4),(3))
282 addi 4, 4, 16
283 STXVD2X (7,(4),(3))
284 addi 4, 4, 16
285 STXVD2X (8,(4),(3))
286 addi 4, 4, 16
287 STXVD2X (9,(4),(3))
288 addi 4, 4, 16
289 STXVD2X (10,(4),(3))
290 addi 4, 4, 16
291 STXVD2X (11,(4),(3))
292 addi 4, 4, 16
293 STXVD2X (12,(4),(3))
294 addi 4, 4, 16
295 STXVD2X (13,(4),(3))
296 addi 4, 4, 16
297 STXVD2X (14,(4),(3))
298 addi 4, 4, 16
299 STXVD2X (15,(4),(3))
300 addi 4, 4, 16
301 STXVD2X (16,(4),(3))
302 addi 4, 4, 16
303 STXVD2X (17,(4),(3))
304 addi 4, 4, 16
305 STXVD2X (18,(4),(3))
306 addi 4, 4, 16
307 STXVD2X (19,(4),(3))
308 addi 4, 4, 16
309 STXVD2X (20,(4),(3))
310 addi 4, 4, 16
311 STXVD2X (21,(4),(3))
312 addi 4, 4, 16
313 STXVD2X (22,(4),(3))
314 addi 4, 4, 16
315 STXVD2X (23,(4),(3))
316 addi 4, 4, 16
317 STXVD2X (24,(4),(3))
318 addi 4, 4, 16
319 STXVD2X (25,(4),(3))
320 addi 4, 4, 16
321 STXVD2X (26,(4),(3))
322 addi 4, 4, 16
323 STXVD2X (27,(4),(3))
324 addi 4, 4, 16
325 STXVD2X (28,(4),(3))
326 addi 4, 4, 16
327 STXVD2X (29,(4),(3))
328 addi 4, 4, 16
329 STXVD2X (30,(4),(3))
330 addi 4, 4, 16
331 STXVD2X (31,(4),(3))
332 addi 4, 4, 16
333 STXVD2X (32,(4),(3))
334 addi 4, 4, 16
335 STXVD2X (33,(4),(3))
336 addi 4, 4, 16
337 STXVD2X (34,(4),(3))
338 addi 4, 4, 16
339 STXVD2X (35,(4),(3))
340 addi 4, 4, 16
341 STXVD2X (36,(4),(3))
342 addi 4, 4, 16
343 STXVD2X (37,(4),(3))
344 addi 4, 4, 16
345 STXVD2X (38,(4),(3))
346 addi 4, 4, 16
347 STXVD2X (39,(4),(3))
348 addi 4, 4, 16
349 STXVD2X (40,(4),(3))
350 addi 4, 4, 16
351 STXVD2X (41,(4),(3))
352 addi 4, 4, 16
353 STXVD2X (42,(4),(3))
354 addi 4, 4, 16
355 STXVD2X (43,(4),(3))
356 addi 4, 4, 16
357 STXVD2X (44,(4),(3))
358 addi 4, 4, 16
359 STXVD2X (45,(4),(3))
360 addi 4, 4, 16
361 STXVD2X (46,(4),(3))
362 addi 4, 4, 16
363 STXVD2X (47,(4),(3))
364 addi 4, 4, 16
365 STXVD2X (48,(4),(3))
366 addi 4, 4, 16
367 STXVD2X (49,(4),(3))
368 addi 4, 4, 16
369 STXVD2X (50,(4),(3))
370 addi 4, 4, 16
371 STXVD2X (51,(4),(3))
372 addi 4, 4, 16
373 STXVD2X (52,(4),(3))
374 addi 4, 4, 16
375 STXVD2X (53,(4),(3))
376 addi 4, 4, 16
377 STXVD2X (54,(4),(3))
378 addi 4, 4, 16
379 STXVD2X (55,(4),(3))
380 addi 4, 4, 16
381 STXVD2X (56,(4),(3))
382 addi 4, 4, 16
383 STXVD2X (57,(4),(3))
384 addi 4, 4, 16
385 STXVD2X (58,(4),(3))
386 addi 4, 4, 16
387 STXVD2X (59,(4),(3))
388 addi 4, 4, 16
389 STXVD2X (60,(4),(3))
390 addi 4, 4, 16
391 STXVD2X (61,(4),(3))
392 addi 4, 4, 16
393 STXVD2X (62,(4),(3))
394 addi 4, 4, 16
395 STXVD2X (63,(4),(3))
396 blr
397FUNC_END(storevsx)
diff --git a/tools/testing/selftests/powerpc/math/fpu_asm.S b/tools/testing/selftests/powerpc/math/fpu_asm.S
index 241f067a510f..8a04bb117b69 100644
--- a/tools/testing/selftests/powerpc/math/fpu_asm.S
+++ b/tools/testing/selftests/powerpc/math/fpu_asm.S
@@ -7,8 +7,8 @@
7 * 2 of the License, or (at your option) any later version. 7 * 2 of the License, or (at your option) any later version.
8 */ 8 */
9 9
10#include "../basic_asm.h" 10#include "basic_asm.h"
11#include "../fpu_asm.h" 11#include "fpu_asm.h"
12 12
13FUNC_START(check_fpu) 13FUNC_START(check_fpu)
14 mr r4,r3 14 mr r4,r3
diff --git a/tools/testing/selftests/powerpc/math/vmx_asm.S b/tools/testing/selftests/powerpc/math/vmx_asm.S
index fd74da488625..cb1e5ae1be99 100644
--- a/tools/testing/selftests/powerpc/math/vmx_asm.S
+++ b/tools/testing/selftests/powerpc/math/vmx_asm.S
@@ -7,8 +7,8 @@
7 * 2 of the License, or (at your option) any later version. 7 * 2 of the License, or (at your option) any later version.
8 */ 8 */
9 9
10#include "../basic_asm.h" 10#include "basic_asm.h"
11#include "../vmx_asm.h" 11#include "vmx_asm.h"
12 12
13# Should be safe from C, only touches r4, r5 and v0,v1,v2 13# Should be safe from C, only touches r4, r5 and v0,v1,v2
14FUNC_START(check_vmx) 14FUNC_START(check_vmx)
diff --git a/tools/testing/selftests/powerpc/math/vsx_asm.S b/tools/testing/selftests/powerpc/math/vsx_asm.S
index a110dd882d5e..8f431f6abc49 100644
--- a/tools/testing/selftests/powerpc/math/vsx_asm.S
+++ b/tools/testing/selftests/powerpc/math/vsx_asm.S
@@ -7,8 +7,8 @@
7 * 2 of the License, or (at your option) any later version. 7 * 2 of the License, or (at your option) any later version.
8 */ 8 */
9 9
10#include "../basic_asm.h" 10#include "basic_asm.h"
11#include "../vsx_asm.h" 11#include "vsx_asm.h"
12 12
13#long check_vsx(vector int *r3); 13#long check_vsx(vector int *r3);
14#This function wraps storeing VSX regs to the end of an array and a 14#This function wraps storeing VSX regs to the end of an array and a
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/.gitignore b/tools/testing/selftests/powerpc/pmu/ebb/.gitignore
index 44b7df14a936..42bddbed8b64 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/.gitignore
+++ b/tools/testing/selftests/powerpc/pmu/ebb/.gitignore
@@ -20,5 +20,3 @@ back_to_back_ebbs_test
20lost_exception_test 20lost_exception_test
21no_handler_test 21no_handler_test
22cycles_with_mmcr2_test 22cycles_with_mmcr2_test
23ebb_lmr
24ebb_lmr_regs \ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/Makefile b/tools/testing/selftests/powerpc/pmu/ebb/Makefile
index 6b0453e60d53..8d2279c4bb4b 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/Makefile
+++ b/tools/testing/selftests/powerpc/pmu/ebb/Makefile
@@ -14,7 +14,7 @@ TEST_PROGS := reg_access_test event_attributes_test cycles_test \
14 fork_cleanup_test ebb_on_child_test \ 14 fork_cleanup_test ebb_on_child_test \
15 ebb_on_willing_child_test back_to_back_ebbs_test \ 15 ebb_on_willing_child_test back_to_back_ebbs_test \
16 lost_exception_test no_handler_test \ 16 lost_exception_test no_handler_test \
17 cycles_with_mmcr2_test ebb_lmr ebb_lmr_regs 17 cycles_with_mmcr2_test
18 18
19all: $(TEST_PROGS) 19all: $(TEST_PROGS)
20 20
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.c
deleted file mode 100644
index c47ebd55ba4d..000000000000
--- a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.c
+++ /dev/null
@@ -1,143 +0,0 @@
1/*
2 * Copyright 2016, Jack Miller, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#include <stdlib.h>
7#include <stdio.h>
8
9#include "ebb.h"
10#include "ebb_lmr.h"
11
12#define SIZE (32 * 1024 * 1024) /* 32M */
13#define LM_SIZE 0 /* Smallest encoding, 32M */
14
15#define SECTIONS 64 /* 1 per bit in LMSER */
16#define SECTION_SIZE (SIZE / SECTIONS)
17#define SECTION_LONGS (SECTION_SIZE / sizeof(long))
18
19static unsigned long *test_mem;
20
21static int lmr_count = 0;
22
23void ebb_lmr_handler(void)
24{
25 lmr_count++;
26}
27
28void ldmx_full_section(unsigned long *mem, int section)
29{
30 unsigned long *ptr;
31 int i;
32
33 for (i = 0; i < SECTION_LONGS; i++) {
34 ptr = &mem[(SECTION_LONGS * section) + i];
35 ldmx((unsigned long) &ptr);
36 ebb_lmr_reset();
37 }
38}
39
40unsigned long section_masks[] = {
41 0x8000000000000000,
42 0xFF00000000000000,
43 0x0000000F70000000,
44 0x8000000000000001,
45 0xF0F0F0F0F0F0F0F0,
46 0x0F0F0F0F0F0F0F0F,
47 0x0
48};
49
50int ebb_lmr_section_test(unsigned long *mem)
51{
52 unsigned long *mask = section_masks;
53 int i;
54
55 for (; *mask; mask++) {
56 mtspr(SPRN_LMSER, *mask);
57 printf("Testing mask 0x%016lx\n", mfspr(SPRN_LMSER));
58
59 for (i = 0; i < 64; i++) {
60 lmr_count = 0;
61 ldmx_full_section(mem, i);
62 if (*mask & (1UL << (63 - i)))
63 FAIL_IF(lmr_count != SECTION_LONGS);
64 else
65 FAIL_IF(lmr_count);
66 }
67 }
68
69 return 0;
70}
71
72int ebb_lmr(void)
73{
74 int i;
75
76 SKIP_IF(!lmr_is_supported());
77
78 setup_ebb_handler(ebb_lmr_handler);
79
80 ebb_global_enable();
81
82 FAIL_IF(posix_memalign((void **)&test_mem, SIZE, SIZE) != 0);
83
84 mtspr(SPRN_LMSER, 0);
85
86 FAIL_IF(mfspr(SPRN_LMSER) != 0);
87
88 mtspr(SPRN_LMRR, ((unsigned long)test_mem | LM_SIZE));
89
90 FAIL_IF(mfspr(SPRN_LMRR) != ((unsigned long)test_mem | LM_SIZE));
91
92 /* Read every single byte to ensure we get no false positives */
93 for (i = 0; i < SECTIONS; i++)
94 ldmx_full_section(test_mem, i);
95
96 FAIL_IF(lmr_count != 0);
97
98 /* Turn on the first section */
99
100 mtspr(SPRN_LMSER, (1UL << 63));
101 FAIL_IF(mfspr(SPRN_LMSER) != (1UL << 63));
102
103 /* Enable LM (BESCR) */
104
105 mtspr(SPRN_BESCR, mfspr(SPRN_BESCR) | BESCR_LME);
106 FAIL_IF(!(mfspr(SPRN_BESCR) & BESCR_LME));
107
108 ldmx((unsigned long)&test_mem);
109
110 FAIL_IF(lmr_count != 1); // exactly one exception
111 FAIL_IF(mfspr(SPRN_BESCR) & BESCR_LME); // LM now disabled
112 FAIL_IF(!(mfspr(SPRN_BESCR) & BESCR_LMEO)); // occurred bit set
113
114 printf("Simple LMR EBB OK\n");
115
116 /* This shouldn't cause an EBB since it's been disabled */
117 ldmx((unsigned long)&test_mem);
118 FAIL_IF(lmr_count != 1);
119
120 printf("LMR disable on EBB OK\n");
121
122 ebb_lmr_reset();
123
124 /* This should cause an EBB or reset is broken */
125 ldmx((unsigned long)&test_mem);
126 FAIL_IF(lmr_count != 2);
127
128 printf("LMR reset EBB OK\n");
129
130 ebb_lmr_reset();
131
132 return ebb_lmr_section_test(test_mem);
133}
134
135int main(void)
136{
137 int ret = test_harness(ebb_lmr, "ebb_lmr");
138
139 if (test_mem)
140 free(test_mem);
141
142 return ret;
143}
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.h b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.h
deleted file mode 100644
index ef50abd557cd..000000000000
--- a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.h
+++ /dev/null
@@ -1,39 +0,0 @@
1#ifndef _SELFTESTS_POWERPC_PMU_EBB_LMR_H
2#define _SELFTESTS_POWERPC_PMU_EBB_LMR_H
3
4#include "reg.h"
5
6#ifndef PPC_FEATURE2_ARCH_3_00
7#define PPC_FEATURE2_ARCH_3_00 0x00800000
8#endif
9
10#define lmr_is_supported() have_hwcap2(PPC_FEATURE2_ARCH_3_00)
11
12static inline void ebb_lmr_reset(void)
13{
14 unsigned long bescr = mfspr(SPRN_BESCR);
15 bescr &= ~(BESCR_LMEO);
16 bescr |= BESCR_LME;
17 mtspr(SPRN_BESCR, bescr);
18}
19
20#define LDMX(t, a, b)\
21 (0x7c00026a | \
22 (((t) & 0x1f) << 21) | \
23 (((a) & 0x1f) << 16) | \
24 (((b) & 0x1f) << 11))
25
26static inline unsigned long ldmx(unsigned long address)
27{
28 unsigned long ret;
29
30 asm volatile ("mr 9, %1\r\n"
31 ".long " __stringify(LDMX(9, 0, 9)) "\r\n"
32 "mr %0, 9\r\n":"=r"(ret)
33 :"r"(address)
34 :"r9");
35
36 return ret;
37}
38
39#endif
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr_regs.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr_regs.c
deleted file mode 100644
index aff4241fd88a..000000000000
--- a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr_regs.c
+++ /dev/null
@@ -1,37 +0,0 @@
1/*
2 * Copyright 2016, Jack Miller, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#include <stdlib.h>
7#include <stdio.h>
8#include <unistd.h>
9
10#include "ebb.h"
11#include "ebb_lmr.h"
12
13#define CHECKS 10000
14
15int ebb_lmr_regs(void)
16{
17 int i;
18
19 SKIP_IF(!lmr_is_supported());
20
21 ebb_global_enable();
22
23 for (i = 0; i < CHECKS; i++) {
24 mtspr(SPRN_LMRR, i << 25); // skip size and rsvd bits
25 mtspr(SPRN_LMSER, i);
26
27 FAIL_IF(mfspr(SPRN_LMRR) != (i << 25));
28 FAIL_IF(mfspr(SPRN_LMSER) != i);
29 }
30
31 return 0;
32}
33
34int main(void)
35{
36 return test_harness(ebb_lmr_regs, "ebb_lmr_regs");
37}
diff --git a/tools/testing/selftests/powerpc/pmu/lib.c b/tools/testing/selftests/powerpc/pmu/lib.c
index 8b992fa5b478..5bf5dd40822b 100644
--- a/tools/testing/selftests/powerpc/pmu/lib.c
+++ b/tools/testing/selftests/powerpc/pmu/lib.c
@@ -193,9 +193,9 @@ bool require_paranoia_below(int level)
193 long current; 193 long current;
194 char *end, buf[16]; 194 char *end, buf[16];
195 FILE *f; 195 FILE *f;
196 int rc; 196 bool rc;
197 197
198 rc = -1; 198 rc = false;
199 199
200 f = fopen(PARANOID_PATH, "r"); 200 f = fopen(PARANOID_PATH, "r");
201 if (!f) { 201 if (!f) {
@@ -218,7 +218,7 @@ bool require_paranoia_below(int level)
218 if (current >= level) 218 if (current >= level)
219 goto out_close; 219 goto out_close;
220 220
221 rc = 0; 221 rc = true;
222out_close: 222out_close:
223 fclose(f); 223 fclose(f);
224out: 224out:
diff --git a/tools/testing/selftests/powerpc/primitives/asm/firmware.h b/tools/testing/selftests/powerpc/primitives/asm/firmware.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/powerpc/primitives/asm/firmware.h
diff --git a/tools/testing/selftests/powerpc/primitives/asm/ppc_asm.h b/tools/testing/selftests/powerpc/primitives/asm/ppc_asm.h
new file mode 120000
index 000000000000..66c8193224e9
--- /dev/null
+++ b/tools/testing/selftests/powerpc/primitives/asm/ppc_asm.h
@@ -0,0 +1 @@
../../../../../../arch/powerpc/include/asm/ppc_asm.h \ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/primitives/asm/processor.h b/tools/testing/selftests/powerpc/primitives/asm/processor.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/powerpc/primitives/asm/processor.h
diff --git a/tools/testing/selftests/powerpc/primitives/linux/stringify.h b/tools/testing/selftests/powerpc/primitives/linux/stringify.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/powerpc/primitives/linux/stringify.h
diff --git a/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c
index 6cae06117b55..ed3239bbfae2 100644
--- a/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c
+++ b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c
@@ -73,20 +73,23 @@ extern char __stop___ex_table[];
73#error implement UCONTEXT_NIA 73#error implement UCONTEXT_NIA
74#endif 74#endif
75 75
76static int segv_error; 76struct extbl_entry {
77 int insn;
78 int fixup;
79};
77 80
78static void segv_handler(int signr, siginfo_t *info, void *ptr) 81static void segv_handler(int signr, siginfo_t *info, void *ptr)
79{ 82{
80 ucontext_t *uc = (ucontext_t *)ptr; 83 ucontext_t *uc = (ucontext_t *)ptr;
81 unsigned long addr = (unsigned long)info->si_addr; 84 unsigned long addr = (unsigned long)info->si_addr;
82 unsigned long *ip = &UCONTEXT_NIA(uc); 85 unsigned long *ip = &UCONTEXT_NIA(uc);
83 unsigned long *ex_p = (unsigned long *)__start___ex_table; 86 struct extbl_entry *entry = (struct extbl_entry *)__start___ex_table;
84 87
85 while (ex_p < (unsigned long *)__stop___ex_table) { 88 while (entry < (struct extbl_entry *)__stop___ex_table) {
86 unsigned long insn, fixup; 89 unsigned long insn, fixup;
87 90
88 insn = *ex_p++; 91 insn = (unsigned long)&entry->insn + entry->insn;
89 fixup = *ex_p++; 92 fixup = (unsigned long)&entry->fixup + entry->fixup;
90 93
91 if (insn == *ip) { 94 if (insn == *ip) {
92 *ip = fixup; 95 *ip = fixup;
@@ -95,7 +98,7 @@ static void segv_handler(int signr, siginfo_t *info, void *ptr)
95 } 98 }
96 99
97 printf("No exception table match for NIA %lx ADDR %lx\n", *ip, addr); 100 printf("No exception table match for NIA %lx ADDR %lx\n", *ip, addr);
98 segv_error++; 101 abort();
99} 102}
100 103
101static void setup_segv_handler(void) 104static void setup_segv_handler(void)
@@ -119,8 +122,10 @@ static int do_one_test(char *p, int page_offset)
119 122
120 got = load_unaligned_zeropad(p); 123 got = load_unaligned_zeropad(p);
121 124
122 if (should != got) 125 if (should != got) {
123 printf("offset %u load_unaligned_zeropad returned 0x%lx, should be 0x%lx\n", page_offset, got, should); 126 printf("offset %u load_unaligned_zeropad returned 0x%lx, should be 0x%lx\n", page_offset, got, should);
127 return 1;
128 }
124 129
125 return 0; 130 return 0;
126} 131}
@@ -145,8 +150,6 @@ static int test_body(void)
145 for (i = 0; i < page_size; i++) 150 for (i = 0; i < page_size; i++)
146 FAIL_IF(do_one_test(mem_region+i, i)); 151 FAIL_IF(do_one_test(mem_region+i, i));
147 152
148 FAIL_IF(segv_error);
149
150 return 0; 153 return 0;
151} 154}
152 155
diff --git a/tools/testing/selftests/powerpc/ptrace/.gitignore b/tools/testing/selftests/powerpc/ptrace/.gitignore
new file mode 100644
index 000000000000..349acfafc95b
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/.gitignore
@@ -0,0 +1,10 @@
1ptrace-gpr
2ptrace-tm-gpr
3ptrace-tm-spd-gpr
4ptrace-tar
5ptrace-tm-tar
6ptrace-tm-spd-tar
7ptrace-vsx
8ptrace-tm-vsx
9ptrace-tm-spd-vsx
10ptrace-tm-spr
diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile
new file mode 100644
index 000000000000..fe6bc60dfc60
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/Makefile
@@ -0,0 +1,14 @@
1TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \
2 ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \
3 ptrace-tm-spd-vsx ptrace-tm-spr
4
5include ../../lib.mk
6
7all: $(TEST_PROGS)
8
9CFLAGS += -m64 -I../../../../../usr/include -I../tm -mhtm
10
11$(TEST_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h
12
13clean:
14 rm -f $(TEST_PROGS) *.o
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-gpr.c b/tools/testing/selftests/powerpc/ptrace/ptrace-gpr.c
new file mode 100644
index 000000000000..0b4ebcc2f485
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-gpr.c
@@ -0,0 +1,123 @@
1/*
2 * Ptrace test for GPR/FPR registers
3 *
4 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include "ptrace.h"
12#include "ptrace-gpr.h"
13#include "reg.h"
14
15/* Tracer and Tracee Shared Data */
16int shm_id;
17int *cptr, *pptr;
18
19float a = FPR_1;
20float b = FPR_2;
21float c = FPR_3;
22
23void gpr(void)
24{
25 unsigned long gpr_buf[18];
26 float fpr_buf[32];
27
28 cptr = (int *)shmat(shm_id, NULL, 0);
29
30 asm __volatile__(
31 ASM_LOAD_GPR_IMMED(gpr_1)
32 ASM_LOAD_FPR_SINGLE_PRECISION(flt_1)
33 :
34 : [gpr_1]"i"(GPR_1), [flt_1] "r" (&a)
35 : "memory", "r6", "r7", "r8", "r9", "r10",
36 "r11", "r12", "r13", "r14", "r15", "r16", "r17",
37 "r18", "r19", "r20", "r21", "r22", "r23", "r24",
38 "r25", "r26", "r27", "r28", "r29", "r30", "r31"
39 );
40
41 cptr[1] = 1;
42
43 while (!cptr[0])
44 asm volatile("" : : : "memory");
45
46 shmdt((void *)cptr);
47 store_gpr(gpr_buf);
48 store_fpr_single_precision(fpr_buf);
49
50 if (validate_gpr(gpr_buf, GPR_3))
51 exit(1);
52
53 if (validate_fpr_float(fpr_buf, c))
54 exit(1);
55
56 exit(0);
57}
58
59int trace_gpr(pid_t child)
60{
61 unsigned long gpr[18];
62 unsigned long fpr[32];
63
64 FAIL_IF(start_trace(child));
65 FAIL_IF(show_gpr(child, gpr));
66 FAIL_IF(validate_gpr(gpr, GPR_1));
67 FAIL_IF(show_fpr(child, fpr));
68 FAIL_IF(validate_fpr(fpr, FPR_1_REP));
69 FAIL_IF(write_gpr(child, GPR_3));
70 FAIL_IF(write_fpr(child, FPR_3_REP));
71 FAIL_IF(stop_trace(child));
72
73 return TEST_PASS;
74}
75
76int ptrace_gpr(void)
77{
78 pid_t pid;
79 int ret, status;
80
81 shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
82 pid = fork();
83 if (pid < 0) {
84 perror("fork() failed");
85 return TEST_FAIL;
86 }
87 if (pid == 0)
88 gpr();
89
90 if (pid) {
91 pptr = (int *)shmat(shm_id, NULL, 0);
92 while (!pptr[1])
93 asm volatile("" : : : "memory");
94
95 ret = trace_gpr(pid);
96 if (ret) {
97 kill(pid, SIGTERM);
98 shmdt((void *)pptr);
99 shmctl(shm_id, IPC_RMID, NULL);
100 return TEST_FAIL;
101 }
102
103 pptr[0] = 1;
104 shmdt((void *)pptr);
105
106 ret = wait(&status);
107 shmctl(shm_id, IPC_RMID, NULL);
108 if (ret != pid) {
109 printf("Child's exit status not captured\n");
110 return TEST_FAIL;
111 }
112
113 return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
114 TEST_PASS;
115 }
116
117 return TEST_PASS;
118}
119
120int main(int argc, char *argv[])
121{
122 return test_harness(ptrace_gpr, "ptrace_gpr");
123}
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-gpr.h b/tools/testing/selftests/powerpc/ptrace/ptrace-gpr.h
new file mode 100644
index 000000000000..e30fef63824c
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-gpr.h
@@ -0,0 +1,74 @@
1/*
2 * Copyright (C) 2015 Anshuman Khandual, 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#define GPR_1 1
10#define GPR_2 2
11#define GPR_3 3
12#define GPR_4 4
13
14#define FPR_1 0.001
15#define FPR_2 0.002
16#define FPR_3 0.003
17#define FPR_4 0.004
18
19#define FPR_1_REP 0x3f50624de0000000
20#define FPR_2_REP 0x3f60624de0000000
21#define FPR_3_REP 0x3f689374c0000000
22#define FPR_4_REP 0x3f70624de0000000
23
24/* Buffer must have 18 elements */
25int validate_gpr(unsigned long *gpr, unsigned long val)
26{
27 int i, found = 1;
28
29 for (i = 0; i < 18; i++) {
30 if (gpr[i] != val) {
31 printf("GPR[%d]: %lx Expected: %lx\n",
32 i+14, gpr[i], val);
33 found = 0;
34 }
35 }
36
37 if (!found)
38 return TEST_FAIL;
39 return TEST_PASS;
40}
41
42/* Buffer must have 32 elements */
43int validate_fpr(unsigned long *fpr, unsigned long val)
44{
45 int i, found = 1;
46
47 for (i = 0; i < 32; i++) {
48 if (fpr[i] != val) {
49 printf("FPR[%d]: %lx Expected: %lx\n", i, fpr[i], val);
50 found = 0;
51 }
52 }
53
54 if (!found)
55 return TEST_FAIL;
56 return TEST_PASS;
57}
58
59/* Buffer must have 32 elements */
60int validate_fpr_float(float *fpr, float val)
61{
62 int i, found = 1;
63
64 for (i = 0; i < 32; i++) {
65 if (fpr[i] != val) {
66 printf("FPR[%d]: %f Expected: %f\n", i, fpr[i], val);
67 found = 0;
68 }
69 }
70
71 if (!found)
72 return TEST_FAIL;
73 return TEST_PASS;
74}
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tar.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tar.c
new file mode 100644
index 000000000000..f9b5069db89b
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tar.c
@@ -0,0 +1,135 @@
1/*
2 * Ptrace test for TAR, PPR, DSCR registers
3 *
4 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include "ptrace.h"
12#include "ptrace-tar.h"
13
14/* Tracer and Tracee Shared Data */
15int shm_id;
16int *cptr;
17int *pptr;
18
19void tar(void)
20{
21 unsigned long reg[3];
22 int ret;
23
24 cptr = (int *)shmat(shm_id, NULL, 0);
25 printf("%-30s TAR: %u PPR: %lx DSCR: %u\n",
26 user_write, TAR_1, PPR_1, DSCR_1);
27
28 mtspr(SPRN_TAR, TAR_1);
29 mtspr(SPRN_PPR, PPR_1);
30 mtspr(SPRN_DSCR, DSCR_1);
31
32 cptr[2] = 1;
33
34 /* Wait on parent */
35 while (!cptr[0])
36 asm volatile("" : : : "memory");
37
38 reg[0] = mfspr(SPRN_TAR);
39 reg[1] = mfspr(SPRN_PPR);
40 reg[2] = mfspr(SPRN_DSCR);
41
42 printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n",
43 user_read, reg[0], reg[1], reg[2]);
44
45 /* Unblock the parent now */
46 cptr[1] = 1;
47 shmdt((int *)cptr);
48
49 ret = validate_tar_registers(reg, TAR_2, PPR_2, DSCR_2);
50 if (ret)
51 exit(1);
52 exit(0);
53}
54
55int trace_tar(pid_t child)
56{
57 unsigned long reg[3];
58
59 FAIL_IF(start_trace(child));
60 FAIL_IF(show_tar_registers(child, reg));
61 printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n",
62 ptrace_read_running, reg[0], reg[1], reg[2]);
63
64 FAIL_IF(validate_tar_registers(reg, TAR_1, PPR_1, DSCR_1));
65 FAIL_IF(stop_trace(child));
66 return TEST_PASS;
67}
68
69int trace_tar_write(pid_t child)
70{
71 FAIL_IF(start_trace(child));
72 FAIL_IF(write_tar_registers(child, TAR_2, PPR_2, DSCR_2));
73 printf("%-30s TAR: %u PPR: %lx DSCR: %u\n",
74 ptrace_write_running, TAR_2, PPR_2, DSCR_2);
75
76 FAIL_IF(stop_trace(child));
77 return TEST_PASS;
78}
79
80int ptrace_tar(void)
81{
82 pid_t pid;
83 int ret, status;
84
85 shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT);
86 pid = fork();
87 if (pid < 0) {
88 perror("fork() failed");
89 return TEST_FAIL;
90 }
91
92 if (pid == 0)
93 tar();
94
95 if (pid) {
96 pptr = (int *)shmat(shm_id, NULL, 0);
97 pptr[0] = 0;
98 pptr[1] = 0;
99
100 while (!pptr[2])
101 asm volatile("" : : : "memory");
102 ret = trace_tar(pid);
103 if (ret)
104 return ret;
105
106 ret = trace_tar_write(pid);
107 if (ret)
108 return ret;
109
110 /* Unblock the child now */
111 pptr[0] = 1;
112
113 /* Wait on child */
114 while (!pptr[1])
115 asm volatile("" : : : "memory");
116
117 shmdt((int *)pptr);
118
119 ret = wait(&status);
120 shmctl(shm_id, IPC_RMID, NULL);
121 if (ret != pid) {
122 printf("Child's exit status not captured\n");
123 return TEST_PASS;
124 }
125
126 return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
127 TEST_PASS;
128 }
129 return TEST_PASS;
130}
131
132int main(int argc, char *argv[])
133{
134 return test_harness(ptrace_tar, "ptrace_tar");
135}
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tar.h b/tools/testing/selftests/powerpc/ptrace/ptrace-tar.h
new file mode 100644
index 000000000000..aed0aac716d2
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tar.h
@@ -0,0 +1,50 @@
1/*
2 * Copyright (C) 2015 Anshuman Khandual, 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#define TAR_1 10
10#define TAR_2 20
11#define TAR_3 30
12#define TAR_4 40
13#define TAR_5 50
14
15#define DSCR_1 100
16#define DSCR_2 200
17#define DSCR_3 300
18#define DSCR_4 400
19#define DSCR_5 500
20
21#define PPR_1 0x4000000000000 /* or 31,31,31*/
22#define PPR_2 0x8000000000000 /* or 1,1,1 */
23#define PPR_3 0xc000000000000 /* or 6,6,6 */
24#define PPR_4 0x10000000000000 /* or 2,2,2 */
25
26char *user_read = "[User Read (Running)]";
27char *user_write = "[User Write (Running)]";
28char *ptrace_read_running = "[Ptrace Read (Running)]";
29char *ptrace_write_running = "[Ptrace Write (Running)]";
30char *ptrace_read_ckpt = "[Ptrace Read (Checkpointed)]";
31char *ptrace_write_ckpt = "[Ptrace Write (Checkpointed)]";
32
33int validate_tar_registers(unsigned long *reg, unsigned long tar,
34 unsigned long ppr, unsigned long dscr)
35{
36 int match = 1;
37
38 if (reg[0] != tar)
39 match = 0;
40
41 if (reg[1] != ppr)
42 match = 0;
43
44 if (reg[2] != dscr)
45 match = 0;
46
47 if (!match)
48 return TEST_FAIL;
49 return TEST_PASS;
50}
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-gpr.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-gpr.c
new file mode 100644
index 000000000000..59206b96e98a
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-gpr.c
@@ -0,0 +1,158 @@
1/*
2 * Ptrace test for GPR/FPR registers in TM context
3 *
4 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include "ptrace.h"
12#include "ptrace-gpr.h"
13#include "tm.h"
14
15/* Tracer and Tracee Shared Data */
16int shm_id;
17unsigned long *cptr, *pptr;
18
19float a = FPR_1;
20float b = FPR_2;
21float c = FPR_3;
22
23void tm_gpr(void)
24{
25 unsigned long gpr_buf[18];
26 unsigned long result, texasr;
27 float fpr_buf[32];
28
29 printf("Starting the child\n");
30 cptr = (unsigned long *)shmat(shm_id, NULL, 0);
31
32trans:
33 cptr[1] = 0;
34 asm __volatile__(
35 ASM_LOAD_GPR_IMMED(gpr_1)
36 ASM_LOAD_FPR_SINGLE_PRECISION(flt_1)
37 "1: ;"
38 "tbegin.;"
39 "beq 2f;"
40 ASM_LOAD_GPR_IMMED(gpr_2)
41 ASM_LOAD_FPR_SINGLE_PRECISION(flt_2)
42 "tsuspend.;"
43 "li 7, 1;"
44 "stw 7, 0(%[cptr1]);"
45 "tresume.;"
46 "b .;"
47
48 "tend.;"
49 "li 0, 0;"
50 "ori %[res], 0, 0;"
51 "b 3f;"
52
53 /* Transaction abort handler */
54 "2: ;"
55 "li 0, 1;"
56 "ori %[res], 0, 0;"
57 "mfspr %[texasr], %[sprn_texasr];"
58
59 "3: ;"
60 : [res] "=r" (result), [texasr] "=r" (texasr)
61 : [gpr_1]"i"(GPR_1), [gpr_2]"i"(GPR_2),
62 [sprn_texasr] "i" (SPRN_TEXASR), [flt_1] "r" (&a),
63 [flt_2] "r" (&b), [cptr1] "r" (&cptr[1])
64 : "memory", "r7", "r8", "r9", "r10",
65 "r11", "r12", "r13", "r14", "r15", "r16",
66 "r17", "r18", "r19", "r20", "r21", "r22",
67 "r23", "r24", "r25", "r26", "r27", "r28",
68 "r29", "r30", "r31"
69 );
70
71 if (result) {
72 if (!cptr[0])
73 goto trans;
74
75 shmdt((void *)cptr);
76 store_gpr(gpr_buf);
77 store_fpr_single_precision(fpr_buf);
78
79 if (validate_gpr(gpr_buf, GPR_3))
80 exit(1);
81
82 if (validate_fpr_float(fpr_buf, c))
83 exit(1);
84
85 exit(0);
86 }
87 shmdt((void *)cptr);
88 exit(1);
89}
90
91int trace_tm_gpr(pid_t child)
92{
93 unsigned long gpr[18];
94 unsigned long fpr[32];
95
96 FAIL_IF(start_trace(child));
97 FAIL_IF(show_gpr(child, gpr));
98 FAIL_IF(validate_gpr(gpr, GPR_2));
99 FAIL_IF(show_fpr(child, fpr));
100 FAIL_IF(validate_fpr(fpr, FPR_2_REP));
101 FAIL_IF(show_ckpt_fpr(child, fpr));
102 FAIL_IF(validate_fpr(fpr, FPR_1_REP));
103 FAIL_IF(show_ckpt_gpr(child, gpr));
104 FAIL_IF(validate_gpr(gpr, GPR_1));
105 FAIL_IF(write_ckpt_gpr(child, GPR_3));
106 FAIL_IF(write_ckpt_fpr(child, FPR_3_REP));
107
108 pptr[0] = 1;
109 FAIL_IF(stop_trace(child));
110
111 return TEST_PASS;
112}
113
114int ptrace_tm_gpr(void)
115{
116 pid_t pid;
117 int ret, status;
118
119 SKIP_IF(!have_htm());
120 shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
121 pid = fork();
122 if (pid < 0) {
123 perror("fork() failed");
124 return TEST_FAIL;
125 }
126 if (pid == 0)
127 tm_gpr();
128
129 if (pid) {
130 pptr = (unsigned long *)shmat(shm_id, NULL, 0);
131
132 while (!pptr[1])
133 asm volatile("" : : : "memory");
134 ret = trace_tm_gpr(pid);
135 if (ret) {
136 kill(pid, SIGTERM);
137 return TEST_FAIL;
138 }
139
140 shmdt((void *)pptr);
141
142 ret = wait(&status);
143 shmctl(shm_id, IPC_RMID, NULL);
144 if (ret != pid) {
145 printf("Child's exit status not captured\n");
146 return TEST_FAIL;
147 }
148
149 return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
150 TEST_PASS;
151 }
152 return TEST_PASS;
153}
154
155int main(int argc, char *argv[])
156{
157 return test_harness(ptrace_tm_gpr, "ptrace_tm_gpr");
158}
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c
new file mode 100644
index 000000000000..327fa943c7f3
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c
@@ -0,0 +1,169 @@
1/*
2 * Ptrace test for GPR/FPR registers in TM Suspend context
3 *
4 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include "ptrace.h"
12#include "ptrace-gpr.h"
13#include "tm.h"
14
15/* Tracer and Tracee Shared Data */
16int shm_id;
17int *cptr, *pptr;
18
19float a = FPR_1;
20float b = FPR_2;
21float c = FPR_3;
22float d = FPR_4;
23
24__attribute__((used)) void wait_parent(void)
25{
26 cptr[2] = 1;
27 while (!cptr[1])
28 asm volatile("" : : : "memory");
29}
30
31void tm_spd_gpr(void)
32{
33 unsigned long gpr_buf[18];
34 unsigned long result, texasr;
35 float fpr_buf[32];
36
37 cptr = (int *)shmat(shm_id, NULL, 0);
38
39trans:
40 cptr[2] = 0;
41 asm __volatile__(
42 ASM_LOAD_GPR_IMMED(gpr_1)
43 ASM_LOAD_FPR_SINGLE_PRECISION(flt_1)
44
45 "1: ;"
46 "tbegin.;"
47 "beq 2f;"
48
49 ASM_LOAD_GPR_IMMED(gpr_2)
50 "tsuspend.;"
51 ASM_LOAD_GPR_IMMED(gpr_4)
52 ASM_LOAD_FPR_SINGLE_PRECISION(flt_4)
53
54 "bl wait_parent;"
55 "tresume.;"
56 "tend.;"
57 "li 0, 0;"
58 "ori %[res], 0, 0;"
59 "b 3f;"
60
61 /* Transaction abort handler */
62 "2: ;"
63 "li 0, 1;"
64 "ori %[res], 0, 0;"
65 "mfspr %[texasr], %[sprn_texasr];"
66
67 "3: ;"
68 : [res] "=r" (result), [texasr] "=r" (texasr)
69 : [gpr_1]"i"(GPR_1), [gpr_2]"i"(GPR_2), [gpr_4]"i"(GPR_4),
70 [sprn_texasr] "i" (SPRN_TEXASR), [flt_1] "r" (&a),
71 [flt_2] "r" (&b), [flt_4] "r" (&d)
72 : "memory", "r5", "r6", "r7",
73 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
74 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
75 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
76 );
77
78 if (result) {
79 if (!cptr[0])
80 goto trans;
81
82 shmdt((void *)cptr);
83 store_gpr(gpr_buf);
84 store_fpr_single_precision(fpr_buf);
85
86 if (validate_gpr(gpr_buf, GPR_3))
87 exit(1);
88
89 if (validate_fpr_float(fpr_buf, c))
90 exit(1);
91 exit(0);
92 }
93 shmdt((void *)cptr);
94 exit(1);
95}
96
97int trace_tm_spd_gpr(pid_t child)
98{
99 unsigned long gpr[18];
100 unsigned long fpr[32];
101
102 FAIL_IF(start_trace(child));
103 FAIL_IF(show_gpr(child, gpr));
104 FAIL_IF(validate_gpr(gpr, GPR_4));
105 FAIL_IF(show_fpr(child, fpr));
106 FAIL_IF(validate_fpr(fpr, FPR_4_REP));
107 FAIL_IF(show_ckpt_fpr(child, fpr));
108 FAIL_IF(validate_fpr(fpr, FPR_1_REP));
109 FAIL_IF(show_ckpt_gpr(child, gpr));
110 FAIL_IF(validate_gpr(gpr, GPR_1));
111 FAIL_IF(write_ckpt_gpr(child, GPR_3));
112 FAIL_IF(write_ckpt_fpr(child, FPR_3_REP));
113
114 pptr[0] = 1;
115 pptr[1] = 1;
116 FAIL_IF(stop_trace(child));
117 return TEST_PASS;
118}
119
120int ptrace_tm_spd_gpr(void)
121{
122 pid_t pid;
123 int ret, status;
124
125 SKIP_IF(!have_htm());
126 shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT);
127 pid = fork();
128 if (pid < 0) {
129 perror("fork() failed");
130 return TEST_FAIL;
131 }
132
133 if (pid == 0)
134 tm_spd_gpr();
135
136 if (pid) {
137 pptr = (int *)shmat(shm_id, NULL, 0);
138 pptr[0] = 0;
139 pptr[1] = 0;
140
141 while (!pptr[2])
142 asm volatile("" : : : "memory");
143 ret = trace_tm_spd_gpr(pid);
144 if (ret) {
145 kill(pid, SIGTERM);
146 shmdt((void *)pptr);
147 shmctl(shm_id, IPC_RMID, NULL);
148 return TEST_FAIL;
149 }
150
151 shmdt((void *)pptr);
152
153 ret = wait(&status);
154 shmctl(shm_id, IPC_RMID, NULL);
155 if (ret != pid) {
156 printf("Child's exit status not captured\n");
157 return TEST_FAIL;
158 }
159
160 return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
161 TEST_PASS;
162 }
163 return TEST_PASS;
164}
165
166int main(int argc, char *argv[])
167{
168 return test_harness(ptrace_tm_spd_gpr, "ptrace_tm_spd_gpr");
169}
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-tar.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-tar.c
new file mode 100644
index 000000000000..b3c061dc9512
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-tar.c
@@ -0,0 +1,174 @@
1/*
2 * Ptrace test for TAR, PPR, DSCR registers in the TM Suspend context
3 *
4 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include "ptrace.h"
12#include "tm.h"
13#include "ptrace-tar.h"
14
15int shm_id;
16int *cptr, *pptr;
17
18__attribute__((used)) void wait_parent(void)
19{
20 cptr[2] = 1;
21 while (!cptr[1])
22 asm volatile("" : : : "memory");
23}
24
25void tm_spd_tar(void)
26{
27 unsigned long result, texasr;
28 unsigned long regs[3];
29 int ret;
30
31 cptr = (int *)shmat(shm_id, NULL, 0);
32
33trans:
34 cptr[2] = 0;
35 asm __volatile__(
36 "li 4, %[tar_1];"
37 "mtspr %[sprn_tar], 4;" /* TAR_1 */
38 "li 4, %[dscr_1];"
39 "mtspr %[sprn_dscr], 4;" /* DSCR_1 */
40 "or 31,31,31;" /* PPR_1*/
41
42 "1: ;"
43 "tbegin.;"
44 "beq 2f;"
45
46 "li 4, %[tar_2];"
47 "mtspr %[sprn_tar], 4;" /* TAR_2 */
48 "li 4, %[dscr_2];"
49 "mtspr %[sprn_dscr], 4;" /* DSCR_2 */
50 "or 1,1,1;" /* PPR_2 */
51
52 "tsuspend.;"
53 "li 4, %[tar_3];"
54 "mtspr %[sprn_tar], 4;" /* TAR_3 */
55 "li 4, %[dscr_3];"
56 "mtspr %[sprn_dscr], 4;" /* DSCR_3 */
57 "or 6,6,6;" /* PPR_3 */
58 "bl wait_parent;"
59 "tresume.;"
60
61 "tend.;"
62 "li 0, 0;"
63 "ori %[res], 0, 0;"
64 "b 3f;"
65
66 /* Transaction abort handler */
67 "2: ;"
68 "li 0, 1;"
69 "ori %[res], 0, 0;"
70 "mfspr %[texasr], %[sprn_texasr];"
71
72 "3: ;"
73
74 : [res] "=r" (result), [texasr] "=r" (texasr)
75 : [val] "r" (cptr[1]), [sprn_dscr]"i"(SPRN_DSCR),
76 [sprn_tar]"i"(SPRN_TAR), [sprn_ppr]"i"(SPRN_PPR),
77 [sprn_texasr]"i"(SPRN_TEXASR), [tar_1]"i"(TAR_1),
78 [dscr_1]"i"(DSCR_1), [tar_2]"i"(TAR_2), [dscr_2]"i"(DSCR_2),
79 [tar_3]"i"(TAR_3), [dscr_3]"i"(DSCR_3)
80 : "memory", "r0", "r1", "r3", "r4", "r5", "r6"
81 );
82
83 /* TM failed, analyse */
84 if (result) {
85 if (!cptr[0])
86 goto trans;
87
88 regs[0] = mfspr(SPRN_TAR);
89 regs[1] = mfspr(SPRN_PPR);
90 regs[2] = mfspr(SPRN_DSCR);
91
92 shmdt(&cptr);
93 printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n",
94 user_read, regs[0], regs[1], regs[2]);
95
96 ret = validate_tar_registers(regs, TAR_4, PPR_4, DSCR_4);
97 if (ret)
98 exit(1);
99 exit(0);
100 }
101 shmdt(&cptr);
102 exit(1);
103}
104
105int trace_tm_spd_tar(pid_t child)
106{
107 unsigned long regs[3];
108
109 FAIL_IF(start_trace(child));
110 FAIL_IF(show_tar_registers(child, regs));
111 printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n",
112 ptrace_read_running, regs[0], regs[1], regs[2]);
113
114 FAIL_IF(validate_tar_registers(regs, TAR_3, PPR_3, DSCR_3));
115 FAIL_IF(show_tm_checkpointed_state(child, regs));
116 printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n",
117 ptrace_read_ckpt, regs[0], regs[1], regs[2]);
118
119 FAIL_IF(validate_tar_registers(regs, TAR_1, PPR_1, DSCR_1));
120 FAIL_IF(write_ckpt_tar_registers(child, TAR_4, PPR_4, DSCR_4));
121 printf("%-30s TAR: %u PPR: %lx DSCR: %u\n",
122 ptrace_write_ckpt, TAR_4, PPR_4, DSCR_4);
123
124 pptr[0] = 1;
125 pptr[1] = 1;
126 FAIL_IF(stop_trace(child));
127 return TEST_PASS;
128}
129
130int ptrace_tm_spd_tar(void)
131{
132 pid_t pid;
133 int ret, status;
134
135 SKIP_IF(!have_htm());
136 shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT);
137 pid = fork();
138 if (pid == 0)
139 tm_spd_tar();
140
141 pptr = (int *)shmat(shm_id, NULL, 0);
142 pptr[0] = 0;
143 pptr[1] = 0;
144
145 if (pid) {
146 while (!pptr[2])
147 asm volatile("" : : : "memory");
148 ret = trace_tm_spd_tar(pid);
149 if (ret) {
150 kill(pid, SIGTERM);
151 shmdt(&pptr);
152 shmctl(shm_id, IPC_RMID, NULL);
153 return TEST_FAIL;
154 }
155
156 shmdt(&pptr);
157
158 ret = wait(&status);
159 shmctl(shm_id, IPC_RMID, NULL);
160 if (ret != pid) {
161 printf("Child's exit status not captured\n");
162 return TEST_FAIL;
163 }
164
165 return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
166 TEST_PASS;
167 }
168 return TEST_PASS;
169}
170
171int main(int argc, char *argv[])
172{
173 return test_harness(ptrace_tm_spd_tar, "ptrace_tm_spd_tar");
174}
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c
new file mode 100644
index 000000000000..0df3c23b7888
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c
@@ -0,0 +1,185 @@
1/*
2 * Ptrace test for VMX/VSX registers in the TM Suspend context
3 *
4 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include "ptrace.h"
12#include "tm.h"
13#include "ptrace-vsx.h"
14
15int shm_id;
16int *cptr, *pptr;
17
18unsigned long fp_load[VEC_MAX];
19unsigned long fp_load_new[VEC_MAX];
20unsigned long fp_store[VEC_MAX];
21unsigned long fp_load_ckpt[VEC_MAX];
22unsigned long fp_load_ckpt_new[VEC_MAX];
23
24__attribute__((used)) void load_vsx(void)
25{
26 loadvsx(fp_load, 0);
27}
28
29__attribute__((used)) void load_vsx_new(void)
30{
31 loadvsx(fp_load_new, 0);
32}
33
34__attribute__((used)) void load_vsx_ckpt(void)
35{
36 loadvsx(fp_load_ckpt, 0);
37}
38
39__attribute__((used)) void wait_parent(void)
40{
41 cptr[2] = 1;
42 while (!cptr[1])
43 asm volatile("" : : : "memory");
44}
45
46void tm_spd_vsx(void)
47{
48 unsigned long result, texasr;
49 int ret;
50
51 cptr = (int *)shmat(shm_id, NULL, 0);
52
53trans:
54 cptr[2] = 0;
55 asm __volatile__(
56 "bl load_vsx_ckpt;"
57
58 "1: ;"
59 "tbegin.;"
60 "beq 2f;"
61
62 "bl load_vsx_new;"
63 "tsuspend.;"
64 "bl load_vsx;"
65 "bl wait_parent;"
66 "tresume.;"
67
68 "tend.;"
69 "li 0, 0;"
70 "ori %[res], 0, 0;"
71 "b 3f;"
72
73 "2: ;"
74 "li 0, 1;"
75 "ori %[res], 0, 0;"
76 "mfspr %[texasr], %[sprn_texasr];"
77
78 "3: ;"
79 : [res] "=r" (result), [texasr] "=r" (texasr)
80 : [fp_load] "r" (fp_load), [fp_load_ckpt] "r" (fp_load_ckpt),
81 [sprn_texasr] "i" (SPRN_TEXASR)
82 : "memory", "r0", "r1", "r2", "r3", "r4",
83 "r8", "r9", "r10", "r11"
84 );
85
86 if (result) {
87 if (!cptr[0])
88 goto trans;
89 shmdt((void *)cptr);
90
91 storevsx(fp_store, 0);
92 ret = compare_vsx_vmx(fp_store, fp_load_ckpt_new);
93 if (ret)
94 exit(1);
95 exit(0);
96 }
97 shmdt((void *)cptr);
98 exit(1);
99}
100
101int trace_tm_spd_vsx(pid_t child)
102{
103 unsigned long vsx[VSX_MAX];
104 unsigned long vmx[VMX_MAX + 2][2];
105
106 FAIL_IF(start_trace(child));
107 FAIL_IF(show_vsx(child, vsx));
108 FAIL_IF(validate_vsx(vsx, fp_load));
109 FAIL_IF(show_vmx(child, vmx));
110 FAIL_IF(validate_vmx(vmx, fp_load));
111 FAIL_IF(show_vsx_ckpt(child, vsx));
112 FAIL_IF(validate_vsx(vsx, fp_load_ckpt));
113 FAIL_IF(show_vmx_ckpt(child, vmx));
114 FAIL_IF(validate_vmx(vmx, fp_load_ckpt));
115
116 memset(vsx, 0, sizeof(vsx));
117 memset(vmx, 0, sizeof(vmx));
118
119 load_vsx_vmx(fp_load_ckpt_new, vsx, vmx);
120
121 FAIL_IF(write_vsx_ckpt(child, vsx));
122 FAIL_IF(write_vmx_ckpt(child, vmx));
123
124 pptr[0] = 1;
125 pptr[1] = 1;
126 FAIL_IF(stop_trace(child));
127
128 return TEST_PASS;
129}
130
131int ptrace_tm_spd_vsx(void)
132{
133 pid_t pid;
134 int ret, status, i;
135
136 SKIP_IF(!have_htm());
137 shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT);
138
139 for (i = 0; i < 128; i++) {
140 fp_load[i] = 1 + rand();
141 fp_load_new[i] = 1 + 2 * rand();
142 fp_load_ckpt[i] = 1 + 3 * rand();
143 fp_load_ckpt_new[i] = 1 + 4 * rand();
144 }
145
146 pid = fork();
147 if (pid < 0) {
148 perror("fork() failed");
149 return TEST_FAIL;
150 }
151
152 if (pid == 0)
153 tm_spd_vsx();
154
155 if (pid) {
156 pptr = (int *)shmat(shm_id, NULL, 0);
157 while (!pptr[2])
158 asm volatile("" : : : "memory");
159
160 ret = trace_tm_spd_vsx(pid);
161 if (ret) {
162 kill(pid, SIGKILL);
163 shmdt((void *)pptr);
164 shmctl(shm_id, IPC_RMID, NULL);
165 return TEST_FAIL;
166 }
167
168 shmdt((void *)pptr);
169 ret = wait(&status);
170 shmctl(shm_id, IPC_RMID, NULL);
171 if (ret != pid) {
172 printf("Child's exit status not captured\n");
173 return TEST_FAIL;
174 }
175
176 return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
177 TEST_PASS;
178 }
179 return TEST_PASS;
180}
181
182int main(int argc, char *argv[])
183{
184 return test_harness(ptrace_tm_spd_vsx, "ptrace_tm_spd_vsx");
185}
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c
new file mode 100644
index 000000000000..94e57cb89769
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c
@@ -0,0 +1,168 @@
1/*
2 * Ptrace test TM SPR registers
3 *
4 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include "ptrace.h"
12#include "tm.h"
13
14/* Tracee and tracer shared data */
15struct shared {
16 int flag;
17 struct tm_spr_regs regs;
18};
19unsigned long tfhar;
20
21int shm_id;
22struct shared *cptr, *pptr;
23
24int shm_id1;
25int *cptr1, *pptr1;
26
27#define TM_KVM_SCHED 0xe0000001ac000001
28int validate_tm_spr(struct tm_spr_regs *regs)
29{
30 FAIL_IF(regs->tm_tfhar != tfhar);
31 FAIL_IF((regs->tm_texasr == TM_KVM_SCHED) && (regs->tm_tfiar != 0));
32
33 return TEST_PASS;
34}
35
36void tm_spr(void)
37{
38 unsigned long result, texasr;
39 int ret;
40
41 cptr = (struct shared *)shmat(shm_id, NULL, 0);
42 cptr1 = (int *)shmat(shm_id1, NULL, 0);
43
44trans:
45 cptr1[0] = 0;
46 asm __volatile__(
47 "1: ;"
48 /* TM failover handler should follow "tbegin.;" */
49 "mflr 31;"
50 "bl 4f;" /* $ = TFHAR - 12 */
51 "4: ;"
52 "mflr %[tfhar];"
53 "mtlr 31;"
54
55 "tbegin.;"
56 "beq 2f;"
57
58 "tsuspend.;"
59 "li 8, 1;"
60 "sth 8, 0(%[cptr1]);"
61 "tresume.;"
62 "b .;"
63
64 "tend.;"
65 "li 0, 0;"
66 "ori %[res], 0, 0;"
67 "b 3f;"
68
69 "2: ;"
70
71 "li 0, 1;"
72 "ori %[res], 0, 0;"
73 "mfspr %[texasr], %[sprn_texasr];"
74
75 "3: ;"
76 : [tfhar] "=r" (tfhar), [res] "=r" (result),
77 [texasr] "=r" (texasr), [cptr1] "=r" (cptr1)
78 : [sprn_texasr] "i" (SPRN_TEXASR)
79 : "memory", "r0", "r1", "r2", "r3", "r4",
80 "r8", "r9", "r10", "r11", "r31"
81 );
82
83 /* There are 2 32bit instructions before tbegin. */
84 tfhar += 12;
85
86 if (result) {
87 if (!cptr->flag)
88 goto trans;
89
90 ret = validate_tm_spr((struct tm_spr_regs *)&cptr->regs);
91 shmdt((void *)cptr);
92 shmdt((void *)cptr1);
93 if (ret)
94 exit(1);
95 exit(0);
96 }
97 shmdt((void *)cptr);
98 shmdt((void *)cptr1);
99 exit(1);
100}
101
102int trace_tm_spr(pid_t child)
103{
104 FAIL_IF(start_trace(child));
105 FAIL_IF(show_tm_spr(child, (struct tm_spr_regs *)&pptr->regs));
106
107 printf("TFHAR: %lx TEXASR: %lx TFIAR: %lx\n", pptr->regs.tm_tfhar,
108 pptr->regs.tm_texasr, pptr->regs.tm_tfiar);
109
110 pptr->flag = 1;
111 FAIL_IF(stop_trace(child));
112
113 return TEST_PASS;
114}
115
116int ptrace_tm_spr(void)
117{
118 pid_t pid;
119 int ret, status;
120
121 SKIP_IF(!have_htm());
122 shm_id = shmget(IPC_PRIVATE, sizeof(struct shared), 0777|IPC_CREAT);
123 shm_id1 = shmget(IPC_PRIVATE, sizeof(int), 0777|IPC_CREAT);
124 pid = fork();
125 if (pid < 0) {
126 perror("fork() failed");
127 return TEST_FAIL;
128 }
129
130 if (pid == 0)
131 tm_spr();
132
133 if (pid) {
134 pptr = (struct shared *)shmat(shm_id, NULL, 0);
135 pptr1 = (int *)shmat(shm_id1, NULL, 0);
136
137 while (!pptr1[0])
138 asm volatile("" : : : "memory");
139 ret = trace_tm_spr(pid);
140 if (ret) {
141 kill(pid, SIGKILL);
142 shmdt((void *)pptr);
143 shmdt((void *)pptr1);
144 shmctl(shm_id, IPC_RMID, NULL);
145 shmctl(shm_id1, IPC_RMID, NULL);
146 return TEST_FAIL;
147 }
148
149 shmdt((void *)pptr);
150 shmdt((void *)pptr1);
151 ret = wait(&status);
152 shmctl(shm_id, IPC_RMID, NULL);
153 shmctl(shm_id1, IPC_RMID, NULL);
154 if (ret != pid) {
155 printf("Child's exit status not captured\n");
156 return TEST_FAIL;
157 }
158
159 return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
160 TEST_PASS;
161 }
162 return TEST_PASS;
163}
164
165int main(int argc, char *argv[])
166{
167 return test_harness(ptrace_tm_spr, "ptrace_tm_spr");
168}
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-tar.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-tar.c
new file mode 100644
index 000000000000..48b462f75023
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-tar.c
@@ -0,0 +1,160 @@
1/*
2 * Ptrace test for TAR, PPR, DSCR registers in the TM context
3 *
4 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include "ptrace.h"
12#include "tm.h"
13#include "ptrace-tar.h"
14
15int shm_id;
16unsigned long *cptr, *pptr;
17
18
19void tm_tar(void)
20{
21 unsigned long result, texasr;
22 unsigned long regs[3];
23 int ret;
24
25 cptr = (unsigned long *)shmat(shm_id, NULL, 0);
26
27trans:
28 cptr[1] = 0;
29 asm __volatile__(
30 "li 4, %[tar_1];"
31 "mtspr %[sprn_tar], 4;" /* TAR_1 */
32 "li 4, %[dscr_1];"
33 "mtspr %[sprn_dscr], 4;" /* DSCR_1 */
34 "or 31,31,31;" /* PPR_1*/
35
36 "1: ;"
37 "tbegin.;"
38 "beq 2f;"
39
40 "li 4, %[tar_2];"
41 "mtspr %[sprn_tar], 4;" /* TAR_2 */
42 "li 4, %[dscr_2];"
43 "mtspr %[sprn_dscr], 4;" /* DSCR_2 */
44 "or 1,1,1;" /* PPR_2 */
45 "tsuspend.;"
46 "li 0, 1;"
47 "stw 0, 0(%[cptr1]);"
48 "tresume.;"
49 "b .;"
50
51 "tend.;"
52 "li 0, 0;"
53 "ori %[res], 0, 0;"
54 "b 3f;"
55
56 /* Transaction abort handler */
57 "2: ;"
58 "li 0, 1;"
59 "ori %[res], 0, 0;"
60 "mfspr %[texasr], %[sprn_texasr];"
61
62 "3: ;"
63
64 : [res] "=r" (result), [texasr] "=r" (texasr)
65 : [sprn_dscr]"i"(SPRN_DSCR), [sprn_tar]"i"(SPRN_TAR),
66 [sprn_ppr]"i"(SPRN_PPR), [sprn_texasr]"i"(SPRN_TEXASR),
67 [tar_1]"i"(TAR_1), [dscr_1]"i"(DSCR_1), [tar_2]"i"(TAR_2),
68 [dscr_2]"i"(DSCR_2), [cptr1] "r" (&cptr[1])
69 : "memory", "r0", "r1", "r3", "r4", "r5", "r6"
70 );
71
72 /* TM failed, analyse */
73 if (result) {
74 if (!cptr[0])
75 goto trans;
76
77 regs[0] = mfspr(SPRN_TAR);
78 regs[1] = mfspr(SPRN_PPR);
79 regs[2] = mfspr(SPRN_DSCR);
80
81 shmdt(&cptr);
82 printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n",
83 user_read, regs[0], regs[1], regs[2]);
84
85 ret = validate_tar_registers(regs, TAR_4, PPR_4, DSCR_4);
86 if (ret)
87 exit(1);
88 exit(0);
89 }
90 shmdt(&cptr);
91 exit(1);
92}
93
94int trace_tm_tar(pid_t child)
95{
96 unsigned long regs[3];
97
98 FAIL_IF(start_trace(child));
99 FAIL_IF(show_tar_registers(child, regs));
100 printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n",
101 ptrace_read_running, regs[0], regs[1], regs[2]);
102
103 FAIL_IF(validate_tar_registers(regs, TAR_2, PPR_2, DSCR_2));
104 FAIL_IF(show_tm_checkpointed_state(child, regs));
105 printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n",
106 ptrace_read_ckpt, regs[0], regs[1], regs[2]);
107
108 FAIL_IF(validate_tar_registers(regs, TAR_1, PPR_1, DSCR_1));
109 FAIL_IF(write_ckpt_tar_registers(child, TAR_4, PPR_4, DSCR_4));
110 printf("%-30s TAR: %u PPR: %lx DSCR: %u\n",
111 ptrace_write_ckpt, TAR_4, PPR_4, DSCR_4);
112
113 pptr[0] = 1;
114 FAIL_IF(stop_trace(child));
115 return TEST_PASS;
116}
117
118int ptrace_tm_tar(void)
119{
120 pid_t pid;
121 int ret, status;
122
123 SKIP_IF(!have_htm());
124 shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
125 pid = fork();
126 if (pid == 0)
127 tm_tar();
128
129 pptr = (unsigned long *)shmat(shm_id, NULL, 0);
130 pptr[0] = 0;
131
132 if (pid) {
133 while (!pptr[1])
134 asm volatile("" : : : "memory");
135 ret = trace_tm_tar(pid);
136 if (ret) {
137 kill(pid, SIGTERM);
138 shmdt(&pptr);
139 shmctl(shm_id, IPC_RMID, NULL);
140 return TEST_FAIL;
141 }
142 shmdt(&pptr);
143
144 ret = wait(&status);
145 shmctl(shm_id, IPC_RMID, NULL);
146 if (ret != pid) {
147 printf("Child's exit status not captured\n");
148 return TEST_FAIL;
149 }
150
151 return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
152 TEST_PASS;
153 }
154 return TEST_PASS;
155}
156
157int main(int argc, char *argv[])
158{
159 return test_harness(ptrace_tm_tar, "ptrace_tm_tar");
160}
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c
new file mode 100644
index 000000000000..b4081e2b22d5
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c
@@ -0,0 +1,168 @@
1/*
2 * Ptrace test for VMX/VSX registers in the TM context
3 *
4 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include "ptrace.h"
12#include "tm.h"
13#include "ptrace-vsx.h"
14
15int shm_id;
16unsigned long *cptr, *pptr;
17
18unsigned long fp_load[VEC_MAX];
19unsigned long fp_store[VEC_MAX];
20unsigned long fp_load_ckpt[VEC_MAX];
21unsigned long fp_load_ckpt_new[VEC_MAX];
22
23__attribute__((used)) void load_vsx(void)
24{
25 loadvsx(fp_load, 0);
26}
27
28__attribute__((used)) void load_vsx_ckpt(void)
29{
30 loadvsx(fp_load_ckpt, 0);
31}
32
33void tm_vsx(void)
34{
35 unsigned long result, texasr;
36 int ret;
37
38 cptr = (unsigned long *)shmat(shm_id, NULL, 0);
39
40trans:
41 cptr[1] = 0;
42 asm __volatile__(
43 "bl load_vsx_ckpt;"
44
45 "1: ;"
46 "tbegin.;"
47 "beq 2f;"
48
49 "bl load_vsx;"
50 "tsuspend.;"
51 "li 7, 1;"
52 "stw 7, 0(%[cptr1]);"
53 "tresume.;"
54 "b .;"
55
56 "tend.;"
57 "li 0, 0;"
58 "ori %[res], 0, 0;"
59 "b 3f;"
60
61 "2: ;"
62 "li 0, 1;"
63 "ori %[res], 0, 0;"
64 "mfspr %[texasr], %[sprn_texasr];"
65
66 "3: ;"
67 : [res] "=r" (result), [texasr] "=r" (texasr)
68 : [fp_load] "r" (fp_load), [fp_load_ckpt] "r" (fp_load_ckpt),
69 [sprn_texasr] "i" (SPRN_TEXASR), [cptr1] "r" (&cptr[1])
70 : "memory", "r0", "r1", "r2", "r3", "r4",
71 "r7", "r8", "r9", "r10", "r11"
72 );
73
74 if (result) {
75 if (!cptr[0])
76 goto trans;
77
78 shmdt((void *)cptr);
79 storevsx(fp_store, 0);
80 ret = compare_vsx_vmx(fp_store, fp_load_ckpt_new);
81 if (ret)
82 exit(1);
83 exit(0);
84 }
85 shmdt((void *)cptr);
86 exit(1);
87}
88
89int trace_tm_vsx(pid_t child)
90{
91 unsigned long vsx[VSX_MAX];
92 unsigned long vmx[VMX_MAX + 2][2];
93
94 FAIL_IF(start_trace(child));
95 FAIL_IF(show_vsx(child, vsx));
96 FAIL_IF(validate_vsx(vsx, fp_load));
97 FAIL_IF(show_vmx(child, vmx));
98 FAIL_IF(validate_vmx(vmx, fp_load));
99 FAIL_IF(show_vsx_ckpt(child, vsx));
100 FAIL_IF(validate_vsx(vsx, fp_load_ckpt));
101 FAIL_IF(show_vmx_ckpt(child, vmx));
102 FAIL_IF(validate_vmx(vmx, fp_load_ckpt));
103 memset(vsx, 0, sizeof(vsx));
104 memset(vmx, 0, sizeof(vmx));
105
106 load_vsx_vmx(fp_load_ckpt_new, vsx, vmx);
107
108 FAIL_IF(write_vsx_ckpt(child, vsx));
109 FAIL_IF(write_vmx_ckpt(child, vmx));
110 pptr[0] = 1;
111 FAIL_IF(stop_trace(child));
112 return TEST_PASS;
113}
114
115int ptrace_tm_vsx(void)
116{
117 pid_t pid;
118 int ret, status, i;
119
120 SKIP_IF(!have_htm());
121 shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
122
123 for (i = 0; i < 128; i++) {
124 fp_load[i] = 1 + rand();
125 fp_load_ckpt[i] = 1 + 2 * rand();
126 fp_load_ckpt_new[i] = 1 + 3 * rand();
127 }
128
129 pid = fork();
130 if (pid < 0) {
131 perror("fork() failed");
132 return TEST_FAIL;
133 }
134
135 if (pid == 0)
136 tm_vsx();
137
138 if (pid) {
139 pptr = (unsigned long *)shmat(shm_id, NULL, 0);
140 while (!pptr[1])
141 asm volatile("" : : : "memory");
142
143 ret = trace_tm_vsx(pid);
144 if (ret) {
145 kill(pid, SIGKILL);
146 shmdt((void *)pptr);
147 shmctl(shm_id, IPC_RMID, NULL);
148 return TEST_FAIL;
149 }
150
151 shmdt((void *)pptr);
152 ret = wait(&status);
153 shmctl(shm_id, IPC_RMID, NULL);
154 if (ret != pid) {
155 printf("Child's exit status not captured\n");
156 return TEST_FAIL;
157 }
158
159 return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
160 TEST_PASS;
161 }
162 return TEST_PASS;
163}
164
165int main(int argc, char *argv[])
166{
167 return test_harness(ptrace_tm_vsx, "ptrace_tm_vsx");
168}
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-vsx.c b/tools/testing/selftests/powerpc/ptrace/ptrace-vsx.c
new file mode 100644
index 000000000000..04084ee7d27b
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-vsx.c
@@ -0,0 +1,117 @@
1/*
2 * Ptrace test for VMX/VSX registers
3 *
4 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include "ptrace.h"
12#include "ptrace-vsx.h"
13
14/* Tracer and Tracee Shared Data */
15int shm_id;
16int *cptr, *pptr;
17
18unsigned long fp_load[VEC_MAX];
19unsigned long fp_load_new[VEC_MAX];
20unsigned long fp_store[VEC_MAX];
21
22void vsx(void)
23{
24 int ret;
25
26 cptr = (int *)shmat(shm_id, NULL, 0);
27 loadvsx(fp_load, 0);
28 cptr[1] = 1;
29
30 while (!cptr[0])
31 asm volatile("" : : : "memory");
32 shmdt((void *) cptr);
33
34 storevsx(fp_store, 0);
35 ret = compare_vsx_vmx(fp_store, fp_load_new);
36 if (ret)
37 exit(1);
38 exit(0);
39}
40
41int trace_vsx(pid_t child)
42{
43 unsigned long vsx[VSX_MAX];
44 unsigned long vmx[VMX_MAX + 2][2];
45
46 FAIL_IF(start_trace(child));
47 FAIL_IF(show_vsx(child, vsx));
48 FAIL_IF(validate_vsx(vsx, fp_load));
49 FAIL_IF(show_vmx(child, vmx));
50 FAIL_IF(validate_vmx(vmx, fp_load));
51
52 memset(vsx, 0, sizeof(vsx));
53 memset(vmx, 0, sizeof(vmx));
54 load_vsx_vmx(fp_load_new, vsx, vmx);
55
56 FAIL_IF(write_vsx(child, vsx));
57 FAIL_IF(write_vmx(child, vmx));
58 FAIL_IF(stop_trace(child));
59
60 return TEST_PASS;
61}
62
63int ptrace_vsx(void)
64{
65 pid_t pid;
66 int ret, status, i;
67
68 shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
69
70 for (i = 0; i < VEC_MAX; i++)
71 fp_load[i] = i + rand();
72
73 for (i = 0; i < VEC_MAX; i++)
74 fp_load_new[i] = i + 2 * rand();
75
76 pid = fork();
77 if (pid < 0) {
78 perror("fork() failed");
79 return TEST_FAIL;
80 }
81
82 if (pid == 0)
83 vsx();
84
85 if (pid) {
86 pptr = (int *)shmat(shm_id, NULL, 0);
87 while (!pptr[1])
88 asm volatile("" : : : "memory");
89
90 ret = trace_vsx(pid);
91 if (ret) {
92 kill(pid, SIGTERM);
93 shmdt((void *)pptr);
94 shmctl(shm_id, IPC_RMID, NULL);
95 return TEST_FAIL;
96 }
97
98 pptr[0] = 1;
99 shmdt((void *)pptr);
100
101 ret = wait(&status);
102 shmctl(shm_id, IPC_RMID, NULL);
103 if (ret != pid) {
104 printf("Child's exit status not captured\n");
105 return TEST_FAIL;
106 }
107
108 return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
109 TEST_PASS;
110 }
111 return TEST_PASS;
112}
113
114int main(int argc, char *argv[])
115{
116 return test_harness(ptrace_vsx, "ptrace_vsx");
117}
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-vsx.h b/tools/testing/selftests/powerpc/ptrace/ptrace-vsx.h
new file mode 100644
index 000000000000..f4e4b427c9d9
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-vsx.h
@@ -0,0 +1,127 @@
1/*
2 * Copyright (C) 2015 Anshuman Khandual, 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#define VEC_MAX 128
10#define VSX_MAX 32
11#define VMX_MAX 32
12
13/*
14 * unsigned long vsx[32]
15 * unsigned long load[128]
16 */
17int validate_vsx(unsigned long *vsx, unsigned long *load)
18{
19 int i;
20
21 for (i = 0; i < VSX_MAX; i++) {
22 if (vsx[i] != load[2 * i + 1]) {
23 printf("vsx[%d]: %lx load[%d] %lx\n",
24 i, vsx[i], 2 * i + 1, load[2 * i + 1]);
25 return TEST_FAIL;
26 }
27 }
28 return TEST_PASS;
29}
30
31/*
32 * unsigned long vmx[32][2]
33 * unsigned long load[128]
34 */
35int validate_vmx(unsigned long vmx[][2], unsigned long *load)
36{
37 int i;
38
39 for (i = 0; i < VMX_MAX; i++) {
40 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
41 if ((vmx[i][0] != load[64 + 2 * i]) ||
42 (vmx[i][1] != load[65 + 2 * i])) {
43 printf("vmx[%d][0]: %lx load[%d] %lx\n",
44 i, vmx[i][0], 64 + 2 * i,
45 load[64 + 2 * i]);
46 printf("vmx[%d][1]: %lx load[%d] %lx\n",
47 i, vmx[i][1], 65 + 2 * i,
48 load[65 + 2 * i]);
49 return TEST_FAIL;
50 }
51 #else /*
52 * In LE each value pair is stored in an
53 * alternate manner.
54 */
55 if ((vmx[i][0] != load[65 + 2 * i]) ||
56 (vmx[i][1] != load[64 + 2 * i])) {
57 printf("vmx[%d][0]: %lx load[%d] %lx\n",
58 i, vmx[i][0], 65 + 2 * i,
59 load[65 + 2 * i]);
60 printf("vmx[%d][1]: %lx load[%d] %lx\n",
61 i, vmx[i][1], 64 + 2 * i,
62 load[64 + 2 * i]);
63 return TEST_FAIL;
64 }
65 #endif
66 }
67 return TEST_PASS;
68}
69
70/*
71 * unsigned long store[128]
72 * unsigned long load[128]
73 */
74int compare_vsx_vmx(unsigned long *store, unsigned long *load)
75{
76 int i;
77
78 for (i = 0; i < VSX_MAX; i++) {
79 if (store[1 + 2 * i] != load[1 + 2 * i]) {
80 printf("store[%d]: %lx load[%d] %lx\n",
81 1 + 2 * i, store[i],
82 1 + 2 * i, load[i]);
83 return TEST_FAIL;
84 }
85 }
86
87 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
88 for (i = 64; i < VEC_MAX; i++) {
89 if (store[i] != load[i]) {
90 printf("store[%d]: %lx load[%d] %lx\n",
91 i, store[i], i, load[i]);
92 return TEST_FAIL;
93 }
94 }
95 #else /* In LE each value pair is stored in an alternate manner */
96 for (i = 64; i < VEC_MAX; i++) {
97 if (!(i % 2) && (store[i] != load[i+1])) {
98 printf("store[%d]: %lx load[%d] %lx\n",
99 i, store[i], i+1, load[i+1]);
100 return TEST_FAIL;
101 }
102 if ((i % 2) && (store[i] != load[i-1])) {
103 printf("here store[%d]: %lx load[%d] %lx\n",
104 i, store[i], i-1, load[i-1]);
105 return TEST_FAIL;
106 }
107 }
108 #endif
109 return TEST_PASS;
110}
111
112void load_vsx_vmx(unsigned long *load, unsigned long *vsx,
113 unsigned long vmx[][2])
114{
115 int i;
116
117 for (i = 0; i < VSX_MAX; i++)
118 vsx[i] = load[1 + 2 * i];
119
120 for (i = 0; i < VMX_MAX; i++) {
121 vmx[i][0] = load[64 + 2 * i];
122 vmx[i][1] = load[65 + 2 * i];
123 }
124}
125
126void loadvsx(void *p, int tmp);
127void storevsx(void *p, int tmp);
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace.h b/tools/testing/selftests/powerpc/ptrace/ptrace.h
new file mode 100644
index 000000000000..19fb825270a1
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace.h
@@ -0,0 +1,711 @@
1/*
2 * Ptrace interface test helper functions
3 *
4 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include <inttypes.h>
12#include <unistd.h>
13#include <stdlib.h>
14#include <string.h>
15#include <malloc.h>
16#include <errno.h>
17#include <time.h>
18#include <sys/ptrace.h>
19#include <sys/ioctl.h>
20#include <sys/uio.h>
21#include <sys/types.h>
22#include <sys/wait.h>
23#include <sys/signal.h>
24#include <sys/ipc.h>
25#include <sys/shm.h>
26#include <sys/user.h>
27#include <linux/elf.h>
28#include <linux/types.h>
29#include <linux/auxvec.h>
30#include "reg.h"
31#include "utils.h"
32
33#define TEST_PASS 0
34#define TEST_FAIL 1
35
36struct fpr_regs {
37 unsigned long fpr[32];
38 unsigned long fpscr;
39};
40
41struct tm_spr_regs {
42 unsigned long tm_tfhar;
43 unsigned long tm_texasr;
44 unsigned long tm_tfiar;
45};
46
47#ifndef NT_PPC_TAR
48#define NT_PPC_TAR 0x103
49#define NT_PPC_PPR 0x104
50#define NT_PPC_DSCR 0x105
51#define NT_PPC_EBB 0x106
52#define NT_PPC_PMU 0x107
53#define NT_PPC_TM_CGPR 0x108
54#define NT_PPC_TM_CFPR 0x109
55#define NT_PPC_TM_CVMX 0x10a
56#define NT_PPC_TM_CVSX 0x10b
57#define NT_PPC_TM_SPR 0x10c
58#define NT_PPC_TM_CTAR 0x10d
59#define NT_PPC_TM_CPPR 0x10e
60#define NT_PPC_TM_CDSCR 0x10f
61#endif
62
63/* Basic ptrace operations */
64int start_trace(pid_t child)
65{
66 int ret;
67
68 ret = ptrace(PTRACE_ATTACH, child, NULL, NULL);
69 if (ret) {
70 perror("ptrace(PTRACE_ATTACH) failed");
71 return TEST_FAIL;
72 }
73 ret = waitpid(child, NULL, 0);
74 if (ret != child) {
75 perror("waitpid() failed");
76 return TEST_FAIL;
77 }
78 return TEST_PASS;
79}
80
81int stop_trace(pid_t child)
82{
83 int ret;
84
85 ret = ptrace(PTRACE_DETACH, child, NULL, NULL);
86 if (ret) {
87 perror("ptrace(PTRACE_DETACH) failed");
88 return TEST_FAIL;
89 }
90 return TEST_PASS;
91}
92
93int cont_trace(pid_t child)
94{
95 int ret;
96
97 ret = ptrace(PTRACE_CONT, child, NULL, NULL);
98 if (ret) {
99 perror("ptrace(PTRACE_CONT) failed");
100 return TEST_FAIL;
101 }
102 return TEST_PASS;
103}
104
105/* TAR, PPR, DSCR */
106int show_tar_registers(pid_t child, unsigned long *out)
107{
108 struct iovec iov;
109 unsigned long *reg;
110 int ret;
111
112 reg = malloc(sizeof(unsigned long));
113 if (!reg) {
114 perror("malloc() failed");
115 return TEST_FAIL;
116 }
117 iov.iov_base = (u64 *) reg;
118 iov.iov_len = sizeof(unsigned long);
119
120 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TAR, &iov);
121 if (ret) {
122 perror("ptrace(PTRACE_GETREGSET) failed");
123 goto fail;
124 }
125 if (out)
126 out[0] = *reg;
127
128 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_PPR, &iov);
129 if (ret) {
130 perror("ptrace(PTRACE_GETREGSET) failed");
131 goto fail;
132 }
133 if (out)
134 out[1] = *reg;
135
136 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_DSCR, &iov);
137 if (ret) {
138 perror("ptrace(PTRACE_GETREGSET) failed");
139 goto fail;
140 }
141 if (out)
142 out[2] = *reg;
143
144 free(reg);
145 return TEST_PASS;
146fail:
147 free(reg);
148 return TEST_FAIL;
149}
150
151int write_tar_registers(pid_t child, unsigned long tar,
152 unsigned long ppr, unsigned long dscr)
153{
154 struct iovec iov;
155 unsigned long *reg;
156 int ret;
157
158 reg = malloc(sizeof(unsigned long));
159 if (!reg) {
160 perror("malloc() failed");
161 return TEST_FAIL;
162 }
163
164 iov.iov_base = (u64 *) reg;
165 iov.iov_len = sizeof(unsigned long);
166
167 *reg = tar;
168 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TAR, &iov);
169 if (ret) {
170 perror("ptrace(PTRACE_SETREGSET) failed");
171 goto fail;
172 }
173
174 *reg = ppr;
175 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_PPR, &iov);
176 if (ret) {
177 perror("ptrace(PTRACE_SETREGSET) failed");
178 goto fail;
179 }
180
181 *reg = dscr;
182 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_DSCR, &iov);
183 if (ret) {
184 perror("ptrace(PTRACE_SETREGSET) failed");
185 goto fail;
186 }
187
188 free(reg);
189 return TEST_PASS;
190fail:
191 free(reg);
192 return TEST_FAIL;
193}
194
195int show_tm_checkpointed_state(pid_t child, unsigned long *out)
196{
197 struct iovec iov;
198 unsigned long *reg;
199 int ret;
200
201 reg = malloc(sizeof(unsigned long));
202 if (!reg) {
203 perror("malloc() failed");
204 return TEST_FAIL;
205 }
206
207 iov.iov_base = (u64 *) reg;
208 iov.iov_len = sizeof(unsigned long);
209
210 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CTAR, &iov);
211 if (ret) {
212 perror("ptrace(PTRACE_GETREGSET) failed");
213 goto fail;
214 }
215 if (out)
216 out[0] = *reg;
217
218 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CPPR, &iov);
219 if (ret) {
220 perror("ptrace(PTRACE_GETREGSET) failed");
221 goto fail;
222 }
223 if (out)
224 out[1] = *reg;
225
226 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CDSCR, &iov);
227 if (ret) {
228 perror("ptrace(PTRACE_GETREGSET) failed");
229 goto fail;
230 }
231 if (out)
232 out[2] = *reg;
233
234 free(reg);
235 return TEST_PASS;
236
237fail:
238 free(reg);
239 return TEST_FAIL;
240}
241
242int write_ckpt_tar_registers(pid_t child, unsigned long tar,
243 unsigned long ppr, unsigned long dscr)
244{
245 struct iovec iov;
246 unsigned long *reg;
247 int ret;
248
249 reg = malloc(sizeof(unsigned long));
250 if (!reg) {
251 perror("malloc() failed");
252 return TEST_FAIL;
253 }
254
255 iov.iov_base = (u64 *) reg;
256 iov.iov_len = sizeof(unsigned long);
257
258 *reg = tar;
259 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CTAR, &iov);
260 if (ret) {
261 perror("ptrace(PTRACE_GETREGSET) failed");
262 goto fail;
263 }
264
265 *reg = ppr;
266 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CPPR, &iov);
267 if (ret) {
268 perror("ptrace(PTRACE_GETREGSET) failed");
269 goto fail;
270 }
271
272 *reg = dscr;
273 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CDSCR, &iov);
274 if (ret) {
275 perror("ptrace(PTRACE_GETREGSET) failed");
276 goto fail;
277 }
278
279 free(reg);
280 return TEST_PASS;
281fail:
282 free(reg);
283 return TEST_FAIL;
284}
285
286/* FPR */
287int show_fpr(pid_t child, unsigned long *fpr)
288{
289 struct fpr_regs *regs;
290 int ret, i;
291
292 regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
293 ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs);
294 if (ret) {
295 perror("ptrace(PTRACE_GETREGSET) failed");
296 return TEST_FAIL;
297 }
298
299 if (fpr) {
300 for (i = 0; i < 32; i++)
301 fpr[i] = regs->fpr[i];
302 }
303 return TEST_PASS;
304}
305
306int write_fpr(pid_t child, unsigned long val)
307{
308 struct fpr_regs *regs;
309 int ret, i;
310
311 regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
312 ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs);
313 if (ret) {
314 perror("ptrace(PTRACE_GETREGSET) failed");
315 return TEST_FAIL;
316 }
317
318 for (i = 0; i < 32; i++)
319 regs->fpr[i] = val;
320
321 ret = ptrace(PTRACE_SETFPREGS, child, NULL, regs);
322 if (ret) {
323 perror("ptrace(PTRACE_GETREGSET) failed");
324 return TEST_FAIL;
325 }
326 return TEST_PASS;
327}
328
329int show_ckpt_fpr(pid_t child, unsigned long *fpr)
330{
331 struct fpr_regs *regs;
332 struct iovec iov;
333 int ret, i;
334
335 regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
336 iov.iov_base = regs;
337 iov.iov_len = sizeof(struct fpr_regs);
338
339 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov);
340 if (ret) {
341 perror("ptrace(PTRACE_GETREGSET) failed");
342 return TEST_FAIL;
343 }
344
345 if (fpr) {
346 for (i = 0; i < 32; i++)
347 fpr[i] = regs->fpr[i];
348 }
349
350 return TEST_PASS;
351}
352
353int write_ckpt_fpr(pid_t child, unsigned long val)
354{
355 struct fpr_regs *regs;
356 struct iovec iov;
357 int ret, i;
358
359 regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
360 iov.iov_base = regs;
361 iov.iov_len = sizeof(struct fpr_regs);
362
363 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov);
364 if (ret) {
365 perror("ptrace(PTRACE_GETREGSET) failed");
366 return TEST_FAIL;
367 }
368
369 for (i = 0; i < 32; i++)
370 regs->fpr[i] = val;
371
372 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CFPR, &iov);
373 if (ret) {
374 perror("ptrace(PTRACE_GETREGSET) failed");
375 return TEST_FAIL;
376 }
377 return TEST_PASS;
378}
379
380/* GPR */
381int show_gpr(pid_t child, unsigned long *gpr)
382{
383 struct pt_regs *regs;
384 int ret, i;
385
386 regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
387 if (!regs) {
388 perror("malloc() failed");
389 return TEST_FAIL;
390 }
391
392 ret = ptrace(PTRACE_GETREGS, child, NULL, regs);
393 if (ret) {
394 perror("ptrace(PTRACE_GETREGSET) failed");
395 return TEST_FAIL;
396 }
397
398 if (gpr) {
399 for (i = 14; i < 32; i++)
400 gpr[i-14] = regs->gpr[i];
401 }
402
403 return TEST_PASS;
404}
405
406int write_gpr(pid_t child, unsigned long val)
407{
408 struct pt_regs *regs;
409 int i, ret;
410
411 regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
412 if (!regs) {
413 perror("malloc() failed");
414 return TEST_FAIL;
415 }
416
417 ret = ptrace(PTRACE_GETREGS, child, NULL, regs);
418 if (ret) {
419 perror("ptrace(PTRACE_GETREGSET) failed");
420 return TEST_FAIL;
421 }
422
423 for (i = 14; i < 32; i++)
424 regs->gpr[i] = val;
425
426 ret = ptrace(PTRACE_SETREGS, child, NULL, regs);
427 if (ret) {
428 perror("ptrace(PTRACE_GETREGSET) failed");
429 return TEST_FAIL;
430 }
431 return TEST_PASS;
432}
433
434int show_ckpt_gpr(pid_t child, unsigned long *gpr)
435{
436 struct pt_regs *regs;
437 struct iovec iov;
438 int ret, i;
439
440 regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
441 if (!regs) {
442 perror("malloc() failed");
443 return TEST_FAIL;
444 }
445
446 iov.iov_base = (u64 *) regs;
447 iov.iov_len = sizeof(struct pt_regs);
448
449 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov);
450 if (ret) {
451 perror("ptrace(PTRACE_GETREGSET) failed");
452 return TEST_FAIL;
453 }
454
455 if (gpr) {
456 for (i = 14; i < 32; i++)
457 gpr[i-14] = regs->gpr[i];
458 }
459
460 return TEST_PASS;
461}
462
463int write_ckpt_gpr(pid_t child, unsigned long val)
464{
465 struct pt_regs *regs;
466 struct iovec iov;
467 int ret, i;
468
469 regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
470 if (!regs) {
471 perror("malloc() failed\n");
472 return TEST_FAIL;
473 }
474 iov.iov_base = (u64 *) regs;
475 iov.iov_len = sizeof(struct pt_regs);
476
477 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov);
478 if (ret) {
479 perror("ptrace(PTRACE_GETREGSET) failed");
480 return TEST_FAIL;
481 }
482
483 for (i = 14; i < 32; i++)
484 regs->gpr[i] = val;
485
486 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CGPR, &iov);
487 if (ret) {
488 perror("ptrace(PTRACE_GETREGSET) failed");
489 return TEST_FAIL;
490 }
491 return TEST_PASS;
492}
493
494/* VMX */
495int show_vmx(pid_t child, unsigned long vmx[][2])
496{
497 int ret;
498
499 ret = ptrace(PTRACE_GETVRREGS, child, 0, vmx);
500 if (ret) {
501 perror("ptrace(PTRACE_GETVRREGS) failed");
502 return TEST_FAIL;
503 }
504 return TEST_PASS;
505}
506
507int show_vmx_ckpt(pid_t child, unsigned long vmx[][2])
508{
509 unsigned long regs[34][2];
510 struct iovec iov;
511 int ret;
512
513 iov.iov_base = (u64 *) regs;
514 iov.iov_len = sizeof(regs);
515 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVMX, &iov);
516 if (ret) {
517 perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVMX) failed");
518 return TEST_FAIL;
519 }
520 memcpy(vmx, regs, sizeof(regs));
521 return TEST_PASS;
522}
523
524
525int write_vmx(pid_t child, unsigned long vmx[][2])
526{
527 int ret;
528
529 ret = ptrace(PTRACE_SETVRREGS, child, 0, vmx);
530 if (ret) {
531 perror("ptrace(PTRACE_SETVRREGS) failed");
532 return TEST_FAIL;
533 }
534 return TEST_PASS;
535}
536
537int write_vmx_ckpt(pid_t child, unsigned long vmx[][2])
538{
539 unsigned long regs[34][2];
540 struct iovec iov;
541 int ret;
542
543 memcpy(regs, vmx, sizeof(regs));
544 iov.iov_base = (u64 *) regs;
545 iov.iov_len = sizeof(regs);
546 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVMX, &iov);
547 if (ret) {
548 perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVMX) failed");
549 return TEST_FAIL;
550 }
551 return TEST_PASS;
552}
553
554/* VSX */
555int show_vsx(pid_t child, unsigned long *vsx)
556{
557 int ret;
558
559 ret = ptrace(PTRACE_GETVSRREGS, child, 0, vsx);
560 if (ret) {
561 perror("ptrace(PTRACE_GETVSRREGS) failed");
562 return TEST_FAIL;
563 }
564 return TEST_PASS;
565}
566
567int show_vsx_ckpt(pid_t child, unsigned long *vsx)
568{
569 unsigned long regs[32];
570 struct iovec iov;
571 int ret;
572
573 iov.iov_base = (u64 *) regs;
574 iov.iov_len = sizeof(regs);
575 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVSX, &iov);
576 if (ret) {
577 perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVSX) failed");
578 return TEST_FAIL;
579 }
580 memcpy(vsx, regs, sizeof(regs));
581 return TEST_PASS;
582}
583
584int write_vsx(pid_t child, unsigned long *vsx)
585{
586 int ret;
587
588 ret = ptrace(PTRACE_SETVSRREGS, child, 0, vsx);
589 if (ret) {
590 perror("ptrace(PTRACE_SETVSRREGS) failed");
591 return TEST_FAIL;
592 }
593 return TEST_PASS;
594}
595
596int write_vsx_ckpt(pid_t child, unsigned long *vsx)
597{
598 unsigned long regs[32];
599 struct iovec iov;
600 int ret;
601
602 memcpy(regs, vsx, sizeof(regs));
603 iov.iov_base = (u64 *) regs;
604 iov.iov_len = sizeof(regs);
605 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVSX, &iov);
606 if (ret) {
607 perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVSX) failed");
608 return TEST_FAIL;
609 }
610 return TEST_PASS;
611}
612
613/* TM SPR */
614int show_tm_spr(pid_t child, struct tm_spr_regs *out)
615{
616 struct tm_spr_regs *regs;
617 struct iovec iov;
618 int ret;
619
620 regs = (struct tm_spr_regs *) malloc(sizeof(struct tm_spr_regs));
621 if (!regs) {
622 perror("malloc() failed");
623 return TEST_FAIL;
624 }
625
626 iov.iov_base = (u64 *) regs;
627 iov.iov_len = sizeof(struct tm_spr_regs);
628
629 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_SPR, &iov);
630 if (ret) {
631 perror("ptrace(PTRACE_GETREGSET) failed");
632 return TEST_FAIL;
633 }
634
635 if (out)
636 memcpy(out, regs, sizeof(struct tm_spr_regs));
637
638 return TEST_PASS;
639}
640
641
642
643/* Analyse TEXASR after TM failure */
644inline unsigned long get_tfiar(void)
645{
646 unsigned long ret;
647
648 asm volatile("mfspr %0,%1" : "=r" (ret) : "i" (SPRN_TFIAR));
649 return ret;
650}
651
652void analyse_texasr(unsigned long texasr)
653{
654 printf("TEXASR: %16lx\t", texasr);
655
656 if (texasr & TEXASR_FP)
657 printf("TEXASR_FP ");
658
659 if (texasr & TEXASR_DA)
660 printf("TEXASR_DA ");
661
662 if (texasr & TEXASR_NO)
663 printf("TEXASR_NO ");
664
665 if (texasr & TEXASR_FO)
666 printf("TEXASR_FO ");
667
668 if (texasr & TEXASR_SIC)
669 printf("TEXASR_SIC ");
670
671 if (texasr & TEXASR_NTC)
672 printf("TEXASR_NTC ");
673
674 if (texasr & TEXASR_TC)
675 printf("TEXASR_TC ");
676
677 if (texasr & TEXASR_TIC)
678 printf("TEXASR_TIC ");
679
680 if (texasr & TEXASR_IC)
681 printf("TEXASR_IC ");
682
683 if (texasr & TEXASR_IFC)
684 printf("TEXASR_IFC ");
685
686 if (texasr & TEXASR_ABT)
687 printf("TEXASR_ABT ");
688
689 if (texasr & TEXASR_SPD)
690 printf("TEXASR_SPD ");
691
692 if (texasr & TEXASR_HV)
693 printf("TEXASR_HV ");
694
695 if (texasr & TEXASR_PR)
696 printf("TEXASR_PR ");
697
698 if (texasr & TEXASR_FS)
699 printf("TEXASR_FS ");
700
701 if (texasr & TEXASR_TE)
702 printf("TEXASR_TE ");
703
704 if (texasr & TEXASR_ROT)
705 printf("TEXASR_ROT ");
706
707 printf("TFIAR :%lx\n", get_tfiar());
708}
709
710void store_gpr(unsigned long *addr);
711void store_fpr(float *addr);
diff --git a/tools/testing/selftests/powerpc/reg.h b/tools/testing/selftests/powerpc/reg.h
deleted file mode 100644
index fddf368ed82f..000000000000
--- a/tools/testing/selftests/powerpc/reg.h
+++ /dev/null
@@ -1,60 +0,0 @@
1/*
2 * Copyright 2014, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#ifndef _SELFTESTS_POWERPC_REG_H
7#define _SELFTESTS_POWERPC_REG_H
8
9#define __stringify_1(x) #x
10#define __stringify(x) __stringify_1(x)
11
12#define mfspr(rn) ({unsigned long rval; \
13 asm volatile("mfspr %0," _str(rn) \
14 : "=r" (rval)); rval; })
15#define mtspr(rn, v) asm volatile("mtspr " _str(rn) ",%0" : \
16 : "r" ((unsigned long)(v)) \
17 : "memory")
18
19#define mb() asm volatile("sync" : : : "memory");
20
21#define SPRN_MMCR2 769
22#define SPRN_MMCRA 770
23#define SPRN_MMCR0 779
24#define MMCR0_PMAO 0x00000080
25#define MMCR0_PMAE 0x04000000
26#define MMCR0_FC 0x80000000
27#define SPRN_EBBHR 804
28#define SPRN_EBBRR 805
29#define SPRN_BESCR 806 /* Branch event status & control register */
30#define SPRN_BESCRS 800 /* Branch event status & control set (1 bits set to 1) */
31#define SPRN_BESCRSU 801 /* Branch event status & control set upper */
32#define SPRN_BESCRR 802 /* Branch event status & control REset (1 bits set to 0) */
33#define SPRN_BESCRRU 803 /* Branch event status & control REset upper */
34
35#define BESCR_PMEO 0x1 /* PMU Event-based exception Occurred */
36#define BESCR_PME (0x1ul << 32) /* PMU Event-based exception Enable */
37#define BESCR_LME (0x1ul << 34) /* Load Monitor Enable */
38#define BESCR_LMEO (0x1ul << 2) /* Load Monitor Exception Occurred */
39
40#define SPRN_LMRR 813 /* Load Monitor Region Register */
41#define SPRN_LMSER 814 /* Load Monitor Section Enable Register */
42
43#define SPRN_PMC1 771
44#define SPRN_PMC2 772
45#define SPRN_PMC3 773
46#define SPRN_PMC4 774
47#define SPRN_PMC5 775
48#define SPRN_PMC6 776
49
50#define SPRN_SIAR 780
51#define SPRN_SDAR 781
52#define SPRN_SIER 768
53
54#define SPRN_TEXASR 0x82
55#define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */
56#define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */
57#define TEXASR_FS 0x08000000
58#define SPRN_TAR 0x32f
59
60#endif /* _SELFTESTS_POWERPC_REG_H */
diff --git a/tools/testing/selftests/powerpc/signal/signal.S b/tools/testing/selftests/powerpc/signal/signal.S
index 7043d521df0a..322f2f1fc327 100644
--- a/tools/testing/selftests/powerpc/signal/signal.S
+++ b/tools/testing/selftests/powerpc/signal/signal.S
@@ -7,7 +7,7 @@
7 * 2 of the License, or (at your option) any later version. 7 * 2 of the License, or (at your option) any later version.
8 */ 8 */
9 9
10#include "../basic_asm.h" 10#include "basic_asm.h"
11 11
12/* long signal_self(pid_t pid, int sig); */ 12/* long signal_self(pid_t pid, int sig); */
13FUNC_START(signal_self) 13FUNC_START(signal_self)
diff --git a/tools/testing/selftests/powerpc/stringloops/memcmp.c b/tools/testing/selftests/powerpc/stringloops/memcmp.c
index 17417dd70708..30b1222380ca 100644
--- a/tools/testing/selftests/powerpc/stringloops/memcmp.c
+++ b/tools/testing/selftests/powerpc/stringloops/memcmp.c
@@ -1,7 +1,7 @@
1#include <malloc.h> 1#include <malloc.h>
2#include <stdlib.h> 2#include <stdlib.h>
3#include <string.h> 3#include <string.h>
4#include "../utils.h" 4#include "utils.h"
5 5
6#define SIZE 256 6#define SIZE 256
7#define ITERATIONS 10000 7#define ITERATIONS 10000
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal.S b/tools/testing/selftests/powerpc/tm/tm-signal.S
index 4e13e8b3a96f..506a4ebaf3ae 100644
--- a/tools/testing/selftests/powerpc/tm/tm-signal.S
+++ b/tools/testing/selftests/powerpc/tm/tm-signal.S
@@ -7,11 +7,11 @@
7 * 2 of the License, or (at your option) any later version. 7 * 2 of the License, or (at your option) any later version.
8 */ 8 */
9 9
10#include "../basic_asm.h" 10#include "basic_asm.h"
11#include "../gpr_asm.h" 11#include "gpr_asm.h"
12#include "../fpu_asm.h" 12#include "fpu_asm.h"
13#include "../vmx_asm.h" 13#include "vmx_asm.h"
14#include "../vsx_asm.h" 14#include "vsx_asm.h"
15 15
16/* 16/*
17 * Large caveat here being that the caller cannot expect the 17 * Large caveat here being that the caller cannot expect the
diff --git a/tools/testing/selftests/powerpc/tm/tm.h b/tools/testing/selftests/powerpc/tm/tm.h
index 2c8da74304e7..0ffff04433c5 100644
--- a/tools/testing/selftests/powerpc/tm/tm.h
+++ b/tools/testing/selftests/powerpc/tm/tm.h
@@ -10,7 +10,7 @@
10#include <asm/cputable.h> 10#include <asm/cputable.h>
11#include <stdbool.h> 11#include <stdbool.h>
12 12
13#include "../utils.h" 13#include "utils.h"
14 14
15static inline bool have_htm(void) 15static inline bool have_htm(void)
16{ 16{
diff --git a/tools/testing/selftests/sigaltstack/.gitignore b/tools/testing/selftests/sigaltstack/.gitignore
new file mode 100644
index 000000000000..35897b0a3f44
--- /dev/null
+++ b/tools/testing/selftests/sigaltstack/.gitignore
@@ -0,0 +1 @@
sas
diff --git a/tools/testing/selftests/sync/.gitignore b/tools/testing/selftests/sync/.gitignore
new file mode 100644
index 000000000000..f5091e7792f2
--- /dev/null
+++ b/tools/testing/selftests/sync/.gitignore
@@ -0,0 +1 @@
sync_test
diff --git a/tools/testing/selftests/sync/Makefile b/tools/testing/selftests/sync/Makefile
new file mode 100644
index 000000000000..87ac400507c0
--- /dev/null
+++ b/tools/testing/selftests/sync/Makefile
@@ -0,0 +1,24 @@
1CFLAGS += -O2 -g -std=gnu89 -pthread -Wall -Wextra
2CFLAGS += -I../../../../usr/include/
3LDFLAGS += -pthread
4
5TEST_PROGS = sync_test
6
7all: $(TEST_PROGS)
8
9include ../lib.mk
10
11OBJS = sync_test.o sync.o
12
13TESTS += sync_alloc.o
14TESTS += sync_fence.o
15TESTS += sync_merge.o
16TESTS += sync_wait.o
17TESTS += sync_stress_parallelism.o
18TESTS += sync_stress_consumer.o
19TESTS += sync_stress_merge.o
20
21sync_test: $(OBJS) $(TESTS)
22
23clean:
24 $(RM) sync_test $(OBJS) $(TESTS)
diff --git a/tools/testing/selftests/sync/sw_sync.h b/tools/testing/selftests/sync/sw_sync.h
new file mode 100644
index 000000000000..e2cfc6bad83e
--- /dev/null
+++ b/tools/testing/selftests/sync/sw_sync.h
@@ -0,0 +1,46 @@
1/*
2 * sw_sync abstraction
3 *
4 * Copyright 2015-2016 Collabora Ltd.
5 *
6 * Based on the implementation from the Android Open Source Project,
7 *
8 * Copyright 2013 Google, Inc
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 * OTHER DEALINGS IN THE SOFTWARE.
27 */
28
29#ifndef SELFTESTS_SW_SYNC_H
30#define SELFTESTS_SW_SYNC_H
31
32/*
33 * sw_sync is mainly intended for testing and should not be compiled into
34 * production kernels
35 */
36
37int sw_sync_timeline_create(void);
38int sw_sync_timeline_is_valid(int fd);
39int sw_sync_timeline_inc(int fd, unsigned int count);
40void sw_sync_timeline_destroy(int fd);
41
42int sw_sync_fence_create(int fd, const char *name, unsigned int value);
43int sw_sync_fence_is_valid(int fd);
44void sw_sync_fence_destroy(int fd);
45
46#endif
diff --git a/tools/testing/selftests/sync/sync.c b/tools/testing/selftests/sync/sync.c
new file mode 100644
index 000000000000..f3d599f249b9
--- /dev/null
+++ b/tools/testing/selftests/sync/sync.c
@@ -0,0 +1,221 @@
1/*
2 * sync / sw_sync abstraction
3 * Copyright 2015-2016 Collabora Ltd.
4 *
5 * Based on the implementation from the Android Open Source Project,
6 *
7 * Copyright 2012 Google, Inc
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#include <fcntl.h>
29#include <malloc.h>
30#include <poll.h>
31#include <stdint.h>
32#include <string.h>
33#include <unistd.h>
34
35#include <sys/ioctl.h>
36#include <sys/stat.h>
37#include <sys/types.h>
38
39#include "sync.h"
40#include "sw_sync.h"
41
42#include <linux/sync_file.h>
43
44
45/* SW_SYNC ioctls */
46struct sw_sync_create_fence_data {
47 __u32 value;
48 char name[32];
49 __s32 fence;
50};
51
52#define SW_SYNC_IOC_MAGIC 'W'
53#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\
54 struct sw_sync_create_fence_data)
55#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
56
57
58int sync_wait(int fd, int timeout)
59{
60 struct pollfd fds;
61
62 fds.fd = fd;
63 fds.events = POLLIN | POLLERR;
64
65 return poll(&fds, 1, timeout);
66}
67
68int sync_merge(const char *name, int fd1, int fd2)
69{
70 struct sync_merge_data data = {};
71 int err;
72
73 data.fd2 = fd2;
74 strncpy(data.name, name, sizeof(data.name) - 1);
75 data.name[sizeof(data.name) - 1] = '\0';
76
77 err = ioctl(fd1, SYNC_IOC_MERGE, &data);
78 if (err < 0)
79 return err;
80
81 return data.fence;
82}
83
84static struct sync_file_info *sync_file_info(int fd)
85{
86 struct sync_file_info *info;
87 struct sync_fence_info *fence_info;
88 int err, num_fences;
89
90 info = calloc(1, sizeof(*info));
91 if (info == NULL)
92 return NULL;
93
94 err = ioctl(fd, SYNC_IOC_FILE_INFO, info);
95 if (err < 0) {
96 free(info);
97 return NULL;
98 }
99
100 num_fences = info->num_fences;
101
102 if (num_fences) {
103 info->flags = 0;
104 info->num_fences = num_fences;
105
106 fence_info = calloc(num_fences, sizeof(*fence_info));
107 if (!fence_info) {
108 free(info);
109 return NULL;
110 }
111
112 info->sync_fence_info = (uint64_t)fence_info;
113
114 err = ioctl(fd, SYNC_IOC_FILE_INFO, info);
115 if (err < 0) {
116 free(fence_info);
117 free(info);
118 return NULL;
119 }
120 }
121
122 return info;
123}
124
125static void sync_file_info_free(struct sync_file_info *info)
126{
127 free((void *)info->sync_fence_info);
128 free(info);
129}
130
131int sync_fence_size(int fd)
132{
133 int count;
134 struct sync_file_info *info = sync_file_info(fd);
135
136 if (!info)
137 return 0;
138
139 count = info->num_fences;
140
141 sync_file_info_free(info);
142
143 return count;
144}
145
146int sync_fence_count_with_status(int fd, int status)
147{
148 unsigned int i, count = 0;
149 struct sync_fence_info *fence_info = NULL;
150 struct sync_file_info *info = sync_file_info(fd);
151
152 if (!info)
153 return -1;
154
155 fence_info = (struct sync_fence_info *)info->sync_fence_info;
156 for (i = 0 ; i < info->num_fences ; i++) {
157 if (fence_info[i].status == status)
158 count++;
159 }
160
161 sync_file_info_free(info);
162
163 return count;
164}
165
166int sw_sync_timeline_create(void)
167{
168 return open("/sys/kernel/debug/sync/sw_sync", O_RDWR);
169}
170
171int sw_sync_timeline_inc(int fd, unsigned int count)
172{
173 __u32 arg = count;
174
175 return ioctl(fd, SW_SYNC_IOC_INC, &arg);
176}
177
178int sw_sync_timeline_is_valid(int fd)
179{
180 int status;
181
182 if (fd == -1)
183 return 0;
184
185 status = fcntl(fd, F_GETFD, 0);
186 return (status >= 0);
187}
188
189void sw_sync_timeline_destroy(int fd)
190{
191 if (sw_sync_timeline_is_valid(fd))
192 close(fd);
193}
194
195int sw_sync_fence_create(int fd, const char *name, unsigned int value)
196{
197 struct sw_sync_create_fence_data data = {};
198 int err;
199
200 data.value = value;
201 strncpy(data.name, name, sizeof(data.name) - 1);
202 data.name[sizeof(data.name) - 1] = '\0';
203
204 err = ioctl(fd, SW_SYNC_IOC_CREATE_FENCE, &data);
205 if (err < 0)
206 return err;
207
208 return data.fence;
209}
210
211int sw_sync_fence_is_valid(int fd)
212{
213 /* Same code! */
214 return sw_sync_timeline_is_valid(fd);
215}
216
217void sw_sync_fence_destroy(int fd)
218{
219 if (sw_sync_fence_is_valid(fd))
220 close(fd);
221}
diff --git a/tools/testing/selftests/sync/sync.h b/tools/testing/selftests/sync/sync.h
new file mode 100644
index 000000000000..fb7156148350
--- /dev/null
+++ b/tools/testing/selftests/sync/sync.h
@@ -0,0 +1,40 @@
1/*
2 * sync abstraction
3 * Copyright 2015-2016 Collabora Ltd.
4 *
5 * Based on the implementation from the Android Open Source Project,
6 *
7 * Copyright 2012 Google, Inc
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#ifndef SELFTESTS_SYNC_H
29#define SELFTESTS_SYNC_H
30
31#define FENCE_STATUS_ERROR (-1)
32#define FENCE_STATUS_ACTIVE (0)
33#define FENCE_STATUS_SIGNALED (1)
34
35int sync_wait(int fd, int timeout);
36int sync_merge(const char *name, int fd1, int fd2);
37int sync_fence_size(int fd);
38int sync_fence_count_with_status(int fd, int status);
39
40#endif
diff --git a/tools/testing/selftests/sync/sync_alloc.c b/tools/testing/selftests/sync/sync_alloc.c
new file mode 100644
index 000000000000..66a28afc05dc
--- /dev/null
+++ b/tools/testing/selftests/sync/sync_alloc.c
@@ -0,0 +1,74 @@
1/*
2 * sync allocation tests
3 * Copyright 2015-2016 Collabora Ltd.
4 *
5 * Based on the implementation from the Android Open Source Project,
6 *
7 * Copyright 2012 Google, Inc
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#include "sync.h"
29#include "sw_sync.h"
30#include "synctest.h"
31
32int test_alloc_timeline(void)
33{
34 int timeline, valid;
35
36 timeline = sw_sync_timeline_create();
37 valid = sw_sync_timeline_is_valid(timeline);
38 ASSERT(valid, "Failure allocating timeline\n");
39
40 sw_sync_timeline_destroy(timeline);
41 return 0;
42}
43
44int test_alloc_fence(void)
45{
46 int timeline, fence, valid;
47
48 timeline = sw_sync_timeline_create();
49 valid = sw_sync_timeline_is_valid(timeline);
50 ASSERT(valid, "Failure allocating timeline\n");
51
52 fence = sw_sync_fence_create(timeline, "allocFence", 1);
53 valid = sw_sync_fence_is_valid(fence);
54 ASSERT(valid, "Failure allocating fence\n");
55
56 sw_sync_fence_destroy(fence);
57 sw_sync_timeline_destroy(timeline);
58 return 0;
59}
60
61int test_alloc_fence_negative(void)
62{
63 int fence, timeline;
64
65 timeline = sw_sync_timeline_create();
66 ASSERT(timeline > 0, "Failure allocating timeline\n");
67
68 fence = sw_sync_fence_create(-1, "fence", 1);
69 ASSERT(fence < 0, "Success allocating negative fence\n");
70
71 sw_sync_fence_destroy(fence);
72 sw_sync_timeline_destroy(timeline);
73 return 0;
74}
diff --git a/tools/testing/selftests/sync/sync_fence.c b/tools/testing/selftests/sync/sync_fence.c
new file mode 100644
index 000000000000..13f175287da3
--- /dev/null
+++ b/tools/testing/selftests/sync/sync_fence.c
@@ -0,0 +1,132 @@
1/*
2 * sync fence tests with one timeline
3 * Copyright 2015-2016 Collabora Ltd.
4 *
5 * Based on the implementation from the Android Open Source Project,
6 *
7 * Copyright 2012 Google, Inc
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#include "sync.h"
29#include "sw_sync.h"
30#include "synctest.h"
31
32int test_fence_one_timeline_wait(void)
33{
34 int fence, valid, ret;
35 int timeline = sw_sync_timeline_create();
36
37 valid = sw_sync_timeline_is_valid(timeline);
38 ASSERT(valid, "Failure allocating timeline\n");
39
40 fence = sw_sync_fence_create(timeline, "allocFence", 5);
41 valid = sw_sync_fence_is_valid(fence);
42 ASSERT(valid, "Failure allocating fence\n");
43
44 /* Wait on fence until timeout */
45 ret = sync_wait(fence, 0);
46 ASSERT(ret == 0, "Failure waiting on fence until timeout\n");
47
48 /* Advance timeline from 0 -> 1 */
49 ret = sw_sync_timeline_inc(timeline, 1);
50 ASSERT(ret == 0, "Failure advancing timeline\n");
51
52 /* Wait on fence until timeout */
53 ret = sync_wait(fence, 0);
54 ASSERT(ret == 0, "Failure waiting on fence until timeout\n");
55
56 /* Signal the fence */
57 ret = sw_sync_timeline_inc(timeline, 4);
58 ASSERT(ret == 0, "Failure signaling the fence\n");
59
60 /* Wait successfully */
61 ret = sync_wait(fence, 0);
62 ASSERT(ret > 0, "Failure waiting on fence\n");
63
64 /* Go even further, and confirm wait still succeeds */
65 ret = sw_sync_timeline_inc(timeline, 10);
66 ASSERT(ret == 0, "Failure going further\n");
67 ret = sync_wait(fence, 0);
68 ASSERT(ret > 0, "Failure waiting ahead\n");
69
70 sw_sync_fence_destroy(fence);
71 sw_sync_timeline_destroy(timeline);
72
73 return 0;
74}
75
76int test_fence_one_timeline_merge(void)
77{
78 int a, b, c, d, valid;
79 int timeline = sw_sync_timeline_create();
80
81 /* create fence a,b,c and then merge them all into fence d */
82 a = sw_sync_fence_create(timeline, "allocFence", 1);
83 b = sw_sync_fence_create(timeline, "allocFence", 2);
84 c = sw_sync_fence_create(timeline, "allocFence", 3);
85
86 valid = sw_sync_fence_is_valid(a) &&
87 sw_sync_fence_is_valid(b) &&
88 sw_sync_fence_is_valid(c);
89 ASSERT(valid, "Failure allocating fences\n");
90
91 d = sync_merge("mergeFence", b, a);
92 d = sync_merge("mergeFence", c, d);
93 valid = sw_sync_fence_is_valid(d);
94 ASSERT(valid, "Failure merging fences\n");
95
96 /* confirm all fences have one active point (even d) */
97 ASSERT(sync_fence_count_with_status(a, FENCE_STATUS_ACTIVE) == 1,
98 "a has too many active fences!\n");
99 ASSERT(sync_fence_count_with_status(a, FENCE_STATUS_ACTIVE) == 1,
100 "b has too many active fences!\n");
101 ASSERT(sync_fence_count_with_status(a, FENCE_STATUS_ACTIVE) == 1,
102 "c has too many active fences!\n");
103 ASSERT(sync_fence_count_with_status(a, FENCE_STATUS_ACTIVE) == 1,
104 "d has too many active fences!\n");
105
106 /* confirm that d is not signaled until the max of a,b,c */
107 sw_sync_timeline_inc(timeline, 1);
108 ASSERT(sync_fence_count_with_status(a, FENCE_STATUS_SIGNALED) == 1,
109 "a did not signal!\n");
110 ASSERT(sync_fence_count_with_status(d, FENCE_STATUS_ACTIVE) == 1,
111 "d signaled too early!\n");
112
113 sw_sync_timeline_inc(timeline, 1);
114 ASSERT(sync_fence_count_with_status(b, FENCE_STATUS_SIGNALED) == 1,
115 "b did not signal!\n");
116 ASSERT(sync_fence_count_with_status(d, FENCE_STATUS_ACTIVE) == 1,
117 "d signaled too early!\n");
118
119 sw_sync_timeline_inc(timeline, 1);
120 ASSERT(sync_fence_count_with_status(c, FENCE_STATUS_SIGNALED) == 1,
121 "c did not signal!\n");
122 ASSERT(sync_fence_count_with_status(d, FENCE_STATUS_ACTIVE) == 0 &&
123 sync_fence_count_with_status(d, FENCE_STATUS_SIGNALED) == 1,
124 "d did not signal!\n");
125
126 sw_sync_fence_destroy(d);
127 sw_sync_fence_destroy(c);
128 sw_sync_fence_destroy(b);
129 sw_sync_fence_destroy(a);
130 sw_sync_timeline_destroy(timeline);
131 return 0;
132}
diff --git a/tools/testing/selftests/sync/sync_merge.c b/tools/testing/selftests/sync/sync_merge.c
new file mode 100644
index 000000000000..8914d43395c7
--- /dev/null
+++ b/tools/testing/selftests/sync/sync_merge.c
@@ -0,0 +1,60 @@
1/*
2 * sync fence merge tests
3 * Copyright 2015-2016 Collabora Ltd.
4 *
5 * Based on the implementation from the Android Open Source Project,
6 *
7 * Copyright 2012 Google, Inc
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#include "sync.h"
29#include "sw_sync.h"
30#include "synctest.h"
31
32int test_fence_merge_same_fence(void)
33{
34 int fence, valid, merged;
35 int timeline = sw_sync_timeline_create();
36
37 valid = sw_sync_timeline_is_valid(timeline);
38 ASSERT(valid, "Failure allocating timeline\n");
39
40 fence = sw_sync_fence_create(timeline, "allocFence", 5);
41 valid = sw_sync_fence_is_valid(fence);
42 ASSERT(valid, "Failure allocating fence\n");
43
44 merged = sync_merge("mergeFence", fence, fence);
45 valid = sw_sync_fence_is_valid(fence);
46 ASSERT(valid, "Failure merging fence\n");
47
48 ASSERT(sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED) == 0,
49 "fence signaled too early!\n");
50
51 sw_sync_timeline_inc(timeline, 5);
52 ASSERT(sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED) == 1,
53 "fence did not signal!\n");
54
55 sw_sync_fence_destroy(merged);
56 sw_sync_fence_destroy(fence);
57 sw_sync_timeline_destroy(timeline);
58
59 return 0;
60}
diff --git a/tools/testing/selftests/sync/sync_stress_consumer.c b/tools/testing/selftests/sync/sync_stress_consumer.c
new file mode 100644
index 000000000000..d9eff8d524f7
--- /dev/null
+++ b/tools/testing/selftests/sync/sync_stress_consumer.c
@@ -0,0 +1,185 @@
1/*
2 * sync stress test: producer/consumer
3 * Copyright 2015-2016 Collabora Ltd.
4 *
5 * Based on the implementation from the Android Open Source Project,
6 *
7 * Copyright 2012 Google, Inc
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#include <pthread.h>
29
30#include "sync.h"
31#include "sw_sync.h"
32#include "synctest.h"
33
34/* IMPORTANT NOTE: if you see this test failing on your system, it may be
35 * due to a shortage of file descriptors. Please ensure your system has
36 * a sensible limit for this test to finish correctly.
37 */
38
39/* Returns 1 on error, 0 on success */
40static int busy_wait_on_fence(int fence)
41{
42 int error, active;
43
44 do {
45 error = sync_fence_count_with_status(fence, FENCE_STATUS_ERROR);
46 ASSERT(error == 0, "Error occurred on fence\n");
47 active = sync_fence_count_with_status(fence,
48 FENCE_STATUS_ACTIVE);
49 } while (active);
50
51 return 0;
52}
53
54static struct {
55 int iterations;
56 int threads;
57 int counter;
58 int consumer_timeline;
59 int *producer_timelines;
60 pthread_mutex_t lock;
61} test_data_mpsc;
62
63static int mpsc_producer_thread(void *d)
64{
65 int id = (long)d;
66 int fence, valid, i;
67 int *producer_timelines = test_data_mpsc.producer_timelines;
68 int consumer_timeline = test_data_mpsc.consumer_timeline;
69 int iterations = test_data_mpsc.iterations;
70
71 for (i = 0; i < iterations; i++) {
72 fence = sw_sync_fence_create(consumer_timeline, "fence", i);
73 valid = sw_sync_fence_is_valid(fence);
74 ASSERT(valid, "Failure creating fence\n");
75
76 /*
77 * Wait for the consumer to finish. Use alternate
78 * means of waiting on the fence
79 */
80
81 if ((iterations + id) % 8 != 0) {
82 ASSERT(sync_wait(fence, -1) > 0,
83 "Failure waiting on fence\n");
84 } else {
85 ASSERT(busy_wait_on_fence(fence) == 0,
86 "Failure waiting on fence\n");
87 }
88
89 /*
90 * Every producer increments the counter, the consumer
91 * checks and erases it
92 */
93 pthread_mutex_lock(&test_data_mpsc.lock);
94 test_data_mpsc.counter++;
95 pthread_mutex_unlock(&test_data_mpsc.lock);
96
97 ASSERT(sw_sync_timeline_inc(producer_timelines[id], 1) == 0,
98 "Error advancing producer timeline\n");
99
100 sw_sync_fence_destroy(fence);
101 }
102
103 return 0;
104}
105
106static int mpcs_consumer_thread(void)
107{
108 int fence, merged, tmp, valid, it, i;
109 int *producer_timelines = test_data_mpsc.producer_timelines;
110 int consumer_timeline = test_data_mpsc.consumer_timeline;
111 int iterations = test_data_mpsc.iterations;
112 int n = test_data_mpsc.threads;
113
114 for (it = 1; it <= iterations; it++) {
115 fence = sw_sync_fence_create(producer_timelines[0], "name", it);
116 for (i = 1; i < n; i++) {
117 tmp = sw_sync_fence_create(producer_timelines[i],
118 "name", it);
119 merged = sync_merge("name", tmp, fence);
120 sw_sync_fence_destroy(tmp);
121 sw_sync_fence_destroy(fence);
122 fence = merged;
123 }
124
125 valid = sw_sync_fence_is_valid(fence);
126 ASSERT(valid, "Failure merging fences\n");
127
128 /*
129 * Make sure we see an increment from every producer thread.
130 * Vary the means by which we wait.
131 */
132 if (iterations % 8 != 0) {
133 ASSERT(sync_wait(fence, -1) > 0,
134 "Producers did not increment as expected\n");
135 } else {
136 ASSERT(busy_wait_on_fence(fence) == 0,
137 "Producers did not increment as expected\n");
138 }
139
140 ASSERT(test_data_mpsc.counter == n * it,
141 "Counter value mismatch!\n");
142
143 /* Release the producer threads */
144 ASSERT(sw_sync_timeline_inc(consumer_timeline, 1) == 0,
145 "Failure releasing producer threads\n");
146
147 sw_sync_fence_destroy(fence);
148 }
149
150 return 0;
151}
152
153int test_consumer_stress_multi_producer_single_consumer(void)
154{
155 int iterations = 1 << 12;
156 int n = 5;
157 long i, ret;
158 int producer_timelines[n];
159 int consumer_timeline;
160 pthread_t threads[n];
161
162 consumer_timeline = sw_sync_timeline_create();
163 for (i = 0; i < n; i++)
164 producer_timelines[i] = sw_sync_timeline_create();
165
166 test_data_mpsc.producer_timelines = producer_timelines;
167 test_data_mpsc.consumer_timeline = consumer_timeline;
168 test_data_mpsc.iterations = iterations;
169 test_data_mpsc.threads = n;
170 test_data_mpsc.counter = 0;
171 pthread_mutex_init(&test_data_mpsc.lock, NULL);
172
173 for (i = 0; i < n; i++) {
174 pthread_create(&threads[i], NULL, (void * (*)(void *))
175 mpsc_producer_thread, (void *)i);
176 }
177
178 /* Consumer thread runs here */
179 ret = mpcs_consumer_thread();
180
181 for (i = 0; i < n; i++)
182 pthread_join(threads[i], NULL);
183
184 return ret;
185}
diff --git a/tools/testing/selftests/sync/sync_stress_merge.c b/tools/testing/selftests/sync/sync_stress_merge.c
new file mode 100644
index 000000000000..99e83ef45fbf
--- /dev/null
+++ b/tools/testing/selftests/sync/sync_stress_merge.c
@@ -0,0 +1,115 @@
1/*
2 * sync stress test: merging
3 * Copyright 2015-2016 Collabora Ltd.
4 *
5 * Based on the implementation from the Android Open Source Project,
6 *
7 * Copyright 2012 Google, Inc
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#include <stdlib.h>
29#include <string.h>
30#include <time.h>
31
32#include "sync.h"
33#include "sw_sync.h"
34#include "synctest.h"
35
36int test_merge_stress_random_merge(void)
37{
38 int i, size, ret;
39 int timeline_count = 32;
40 int merge_count = 1024 * 32;
41 int timelines[timeline_count];
42 int fence_map[timeline_count];
43 int fence, tmpfence, merged, valid;
44 int timeline, timeline_offset, sync_point;
45
46 srand(time(NULL));
47
48 for (i = 0; i < timeline_count; i++)
49 timelines[i] = sw_sync_timeline_create();
50
51 fence = sw_sync_fence_create(timelines[0], "fence", 0);
52 valid = sw_sync_fence_is_valid(fence);
53 ASSERT(valid, "Failure creating fence\n");
54
55 memset(fence_map, -1, sizeof(fence_map));
56 fence_map[0] = 0;
57
58 /*
59 * Randomly create sync_points out of a fixed set of timelines,
60 * and merge them together
61 */
62 for (i = 0; i < merge_count; i++) {
63 /* Generate sync_point. */
64 timeline_offset = rand() % timeline_count;
65 timeline = timelines[timeline_offset];
66 sync_point = rand();
67
68 /* Keep track of the latest sync_point in each timeline. */
69 if (fence_map[timeline_offset] == -1)
70 fence_map[timeline_offset] = sync_point;
71 else if (fence_map[timeline_offset] < sync_point)
72 fence_map[timeline_offset] = sync_point;
73
74 /* Merge */
75 tmpfence = sw_sync_fence_create(timeline, "fence", sync_point);
76 merged = sync_merge("merge", tmpfence, fence);
77 sw_sync_fence_destroy(tmpfence);
78 sw_sync_fence_destroy(fence);
79 fence = merged;
80
81 valid = sw_sync_fence_is_valid(merged);
82 ASSERT(valid, "Failure creating fence i\n");
83 }
84
85 size = 0;
86 for (i = 0; i < timeline_count; i++)
87 if (fence_map[i] != -1)
88 size++;
89
90 /* Confirm our map matches the fence. */
91 ASSERT(sync_fence_size(fence) == size,
92 "Quantity of elements not matching\n");
93
94 /* Trigger the merged fence */
95 for (i = 0; i < timeline_count; i++) {
96 if (fence_map[i] != -1) {
97 ret = sync_wait(fence, 0);
98 ASSERT(ret == 0,
99 "Failure waiting on fence until timeout\n");
100 /* Increment the timeline to the last sync_point */
101 sw_sync_timeline_inc(timelines[i], fence_map[i]);
102 }
103 }
104
105 /* Check that the fence is triggered. */
106 ret = sync_wait(fence, 0);
107 ASSERT(ret > 0, "Failure triggering fence\n");
108
109 sw_sync_fence_destroy(fence);
110
111 for (i = 0; i < timeline_count; i++)
112 sw_sync_timeline_destroy(timelines[i]);
113
114 return 0;
115}
diff --git a/tools/testing/selftests/sync/sync_stress_parallelism.c b/tools/testing/selftests/sync/sync_stress_parallelism.c
new file mode 100644
index 000000000000..e6c9be671dfc
--- /dev/null
+++ b/tools/testing/selftests/sync/sync_stress_parallelism.c
@@ -0,0 +1,111 @@
1/*
2 * sync stress test: parallelism
3 * Copyright 2015-2016 Collabora Ltd.
4 *
5 * Based on the implementation from the Android Open Source Project,
6 *
7 * Copyright 2012 Google, Inc
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#include <pthread.h>
29
30#include "sync.h"
31#include "sw_sync.h"
32#include "synctest.h"
33
34static struct {
35 int iterations;
36 int timeline;
37 int counter;
38} test_data_two_threads;
39
40static int test_stress_two_threads_shared_timeline_thread(void *d)
41{
42 int thread_id = (long)d;
43 int timeline = test_data_two_threads.timeline;
44 int iterations = test_data_two_threads.iterations;
45 int fence, valid, ret, i;
46
47 for (i = 0; i < iterations; i++) {
48 fence = sw_sync_fence_create(timeline, "fence",
49 i * 2 + thread_id);
50 valid = sw_sync_fence_is_valid(fence);
51 ASSERT(valid, "Failure allocating fence\n");
52
53 /* Wait on the prior thread to complete */
54 ret = sync_wait(fence, -1);
55 ASSERT(ret > 0, "Problem occurred on prior thread\n");
56
57 /*
58 * Confirm the previous thread's writes are visible
59 * and then increment
60 */
61 ASSERT(test_data_two_threads.counter == i * 2 + thread_id,
62 "Counter got damaged!\n");
63 test_data_two_threads.counter++;
64
65 /* Kick off the other thread */
66 ret = sw_sync_timeline_inc(timeline, 1);
67 ASSERT(ret == 0, "Advancing timeline failed\n");
68
69 sw_sync_fence_destroy(fence);
70 }
71
72 return 0;
73}
74
75int test_stress_two_threads_shared_timeline(void)
76{
77 pthread_t a, b;
78 int valid;
79 int timeline = sw_sync_timeline_create();
80
81 valid = sw_sync_timeline_is_valid(timeline);
82 ASSERT(valid, "Failure allocating timeline\n");
83
84 test_data_two_threads.iterations = 1 << 16;
85 test_data_two_threads.counter = 0;
86 test_data_two_threads.timeline = timeline;
87
88 /*
89 * Use a single timeline to synchronize two threads
90 * hammmering on the same counter.
91 */
92
93 pthread_create(&a, NULL, (void *(*)(void *))
94 test_stress_two_threads_shared_timeline_thread,
95 (void *)0);
96 pthread_create(&b, NULL, (void *(*)(void *))
97 test_stress_two_threads_shared_timeline_thread,
98 (void *)1);
99
100 pthread_join(a, NULL);
101 pthread_join(b, NULL);
102
103 /* make sure the threads did not trample on one another */
104 ASSERT(test_data_two_threads.counter ==
105 test_data_two_threads.iterations * 2,
106 "Counter has unexpected value\n");
107
108 sw_sync_timeline_destroy(timeline);
109
110 return 0;
111}
diff --git a/tools/testing/selftests/sync/sync_test.c b/tools/testing/selftests/sync/sync_test.c
new file mode 100644
index 000000000000..9ea08d9f0b13
--- /dev/null
+++ b/tools/testing/selftests/sync/sync_test.c
@@ -0,0 +1,79 @@
1/*
2 * sync test runner
3 * Copyright 2015-2016 Collabora Ltd.
4 *
5 * Based on the implementation from the Android Open Source Project,
6 *
7 * Copyright 2012 Google, Inc
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#include <stdio.h>
29#include <unistd.h>
30#include <stdlib.h>
31#include <sys/types.h>
32#include <sys/wait.h>
33
34#include "synctest.h"
35
36static int run_test(int (*test)(void), char *name)
37{
38 int result;
39 pid_t childpid;
40
41 fflush(stdout);
42 childpid = fork();
43
44 if (childpid) {
45 waitpid(childpid, &result, 0);
46 if (WIFEXITED(result))
47 return WEXITSTATUS(result);
48 return 1;
49 }
50
51 printf("[RUN]\tExecuting %s\n", name);
52 exit(test());
53}
54
55int main(void)
56{
57 int err = 0;
58
59 printf("[RUN]\tTesting sync framework\n");
60
61 err += RUN_TEST(test_alloc_timeline);
62 err += RUN_TEST(test_alloc_fence);
63 err += RUN_TEST(test_alloc_fence_negative);
64
65 err += RUN_TEST(test_fence_one_timeline_wait);
66 err += RUN_TEST(test_fence_one_timeline_merge);
67 err += RUN_TEST(test_fence_merge_same_fence);
68 err += RUN_TEST(test_fence_multi_timeline_wait);
69 err += RUN_TEST(test_stress_two_threads_shared_timeline);
70 err += RUN_TEST(test_consumer_stress_multi_producer_single_consumer);
71 err += RUN_TEST(test_merge_stress_random_merge);
72
73 if (err)
74 printf("[FAIL]\tsync errors: %d\n", err);
75 else
76 printf("[OK]\tsync\n");
77
78 return !!err;
79}
diff --git a/tools/testing/selftests/sync/sync_wait.c b/tools/testing/selftests/sync/sync_wait.c
new file mode 100644
index 000000000000..d69b752f6550
--- /dev/null
+++ b/tools/testing/selftests/sync/sync_wait.c
@@ -0,0 +1,91 @@
1/*
2 * sync fence wait tests
3 * Copyright 2015-2016 Collabora Ltd.
4 *
5 * Based on the implementation from the Android Open Source Project,
6 *
7 * Copyright 2012 Google, Inc
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#include "sync.h"
29#include "sw_sync.h"
30#include "synctest.h"
31
32int test_fence_multi_timeline_wait(void)
33{
34 int timelineA, timelineB, timelineC;
35 int fenceA, fenceB, fenceC, merged;
36 int valid, active, signaled, ret;
37
38 timelineA = sw_sync_timeline_create();
39 timelineB = sw_sync_timeline_create();
40 timelineC = sw_sync_timeline_create();
41
42 fenceA = sw_sync_fence_create(timelineA, "fenceA", 5);
43 fenceB = sw_sync_fence_create(timelineB, "fenceB", 5);
44 fenceC = sw_sync_fence_create(timelineC, "fenceC", 5);
45
46 merged = sync_merge("mergeFence", fenceB, fenceA);
47 merged = sync_merge("mergeFence", fenceC, merged);
48
49 valid = sw_sync_fence_is_valid(merged);
50 ASSERT(valid, "Failure merging fence from various timelines\n");
51
52 /* Confirm fence isn't signaled */
53 active = sync_fence_count_with_status(merged, FENCE_STATUS_ACTIVE);
54 ASSERT(active == 3, "Fence signaled too early!\n");
55
56 ret = sync_wait(merged, 0);
57 ASSERT(ret == 0,
58 "Failure waiting on fence until timeout\n");
59
60 ret = sw_sync_timeline_inc(timelineA, 5);
61 active = sync_fence_count_with_status(merged, FENCE_STATUS_ACTIVE);
62 signaled = sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED);
63 ASSERT(active == 2 && signaled == 1,
64 "Fence did not signal properly!\n");
65
66 ret = sw_sync_timeline_inc(timelineB, 5);
67 active = sync_fence_count_with_status(merged, FENCE_STATUS_ACTIVE);
68 signaled = sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED);
69 ASSERT(active == 1 && signaled == 2,
70 "Fence did not signal properly!\n");
71
72 ret = sw_sync_timeline_inc(timelineC, 5);
73 active = sync_fence_count_with_status(merged, FENCE_STATUS_ACTIVE);
74 signaled = sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED);
75 ASSERT(active == 0 && signaled == 3,
76 "Fence did not signal properly!\n");
77
78 /* confirm you can successfully wait */
79 ret = sync_wait(merged, 100);
80 ASSERT(ret > 0, "Failure waiting on signaled fence\n");
81
82 sw_sync_fence_destroy(merged);
83 sw_sync_fence_destroy(fenceC);
84 sw_sync_fence_destroy(fenceB);
85 sw_sync_fence_destroy(fenceA);
86 sw_sync_timeline_destroy(timelineC);
87 sw_sync_timeline_destroy(timelineB);
88 sw_sync_timeline_destroy(timelineA);
89
90 return 0;
91}
diff --git a/tools/testing/selftests/sync/synctest.h b/tools/testing/selftests/sync/synctest.h
new file mode 100644
index 000000000000..e7d1d57dba7a
--- /dev/null
+++ b/tools/testing/selftests/sync/synctest.h
@@ -0,0 +1,66 @@
1/*
2 * sync tests
3 * Copyright 2015-2016 Collabora Ltd.
4 *
5 * Based on the implementation from the Android Open Source Project,
6 *
7 * Copyright 2012 Google, Inc
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#ifndef SELFTESTS_SYNCTEST_H
29#define SELFTESTS_SYNCTEST_H
30
31#include <stdio.h>
32
33#define ASSERT(cond, msg) do { \
34 if (!(cond)) { \
35 printf("[ERROR]\t%s", (msg)); \
36 return 1; \
37 } \
38} while (0)
39
40#define RUN_TEST(x) run_test((x), #x)
41
42/* Allocation tests */
43int test_alloc_timeline(void);
44int test_alloc_fence(void);
45int test_alloc_fence_negative(void);
46
47/* Fence tests with one timeline */
48int test_fence_one_timeline_wait(void);
49int test_fence_one_timeline_merge(void);
50
51/* Fence merge tests */
52int test_fence_merge_same_fence(void);
53
54/* Fence wait tests */
55int test_fence_multi_timeline_wait(void);
56
57/* Stress test - parallelism */
58int test_stress_two_threads_shared_timeline(void);
59
60/* Stress test - consumer */
61int test_consumer_stress_multi_producer_single_consumer(void);
62
63/* Stress test - merging */
64int test_merge_stress_random_merge(void);
65
66#endif
diff --git a/tools/testing/selftests/timers/.gitignore b/tools/testing/selftests/timers/.gitignore
index 68f3fc71ac44..cc986621f512 100644
--- a/tools/testing/selftests/timers/.gitignore
+++ b/tools/testing/selftests/timers/.gitignore
@@ -17,3 +17,4 @@ skew_consistency
17threadtest 17threadtest
18valid-adjtimex 18valid-adjtimex
19adjtick 19adjtick
20set-tz
diff --git a/tools/usb/usbip/.gitignore b/tools/usb/usbip/.gitignore
index 9aad9e30a8ba..03b892c8bd8c 100644
--- a/tools/usb/usbip/.gitignore
+++ b/tools/usb/usbip/.gitignore
@@ -2,6 +2,7 @@ Makefile
2Makefile.in 2Makefile.in
3aclocal.m4 3aclocal.m4
4autom4te.cache/ 4autom4te.cache/
5compile
5config.guess 6config.guess
6config.h 7config.h
7config.h.in 8config.h.in
@@ -21,7 +22,10 @@ src/Makefile.in
21stamp-h1 22stamp-h1
22libsrc/libusbip.la 23libsrc/libusbip.la
23libsrc/libusbip_la-names.lo 24libsrc/libusbip_la-names.lo
25libsrc/libusbip_la-sysfs_utils.lo
24libsrc/libusbip_la-usbip_common.lo 26libsrc/libusbip_la-usbip_common.lo
27libsrc/libusbip_la-usbip_device_driver.lo
28libsrc/libusbip_la-usbip_host_common.lo
25libsrc/libusbip_la-usbip_host_driver.lo 29libsrc/libusbip_la-usbip_host_driver.lo
26libsrc/libusbip_la-vhci_driver.lo 30libsrc/libusbip_la-vhci_driver.lo
27src/usbip 31src/usbip
diff --git a/tools/usb/usbip/src/usbipd.c b/tools/usb/usbip/src/usbipd.c
index a0972dea9e6c..009afb4a3aae 100644
--- a/tools/usb/usbip/src/usbipd.c
+++ b/tools/usb/usbip/src/usbipd.c
@@ -398,13 +398,6 @@ static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[],
398 * (see do_standalone_mode()) */ 398 * (see do_standalone_mode()) */
399 usbip_net_set_v6only(sock); 399 usbip_net_set_v6only(sock);
400 400
401 if (sock >= FD_SETSIZE) {
402 err("FD_SETSIZE: %s: sock=%d, max=%d",
403 ai_buf, sock, FD_SETSIZE);
404 close(sock);
405 continue;
406 }
407
408 ret = bind(sock, ai->ai_addr, ai->ai_addrlen); 401 ret = bind(sock, ai->ai_addr, ai->ai_addrlen);
409 if (ret < 0) { 402 if (ret < 0) {
410 err("bind: %s: %d (%s)", 403 err("bind: %s: %d (%s)",
diff --git a/tools/virtio/linux/compiler.h b/tools/virtio/linux/compiler.h
index 845960e1cbf2..c9ccfd42ec13 100644
--- a/tools/virtio/linux/compiler.h
+++ b/tools/virtio/linux/compiler.h
@@ -4,6 +4,6 @@
4#define WRITE_ONCE(var, val) \ 4#define WRITE_ONCE(var, val) \
5 (*((volatile typeof(val) *)(&(var))) = (val)) 5 (*((volatile typeof(val) *)(&(var))) = (val))
6 6
7#define READ_ONCE(var) (*((volatile typeof(val) *)(&(var)))) 7#define READ_ONCE(var) (*((volatile typeof(var) *)(&(var))))
8 8
9#endif 9#endif
diff --git a/tools/virtio/linux/uaccess.h b/tools/virtio/linux/uaccess.h
index 0a578fe18653..fa05d01b2c90 100644
--- a/tools/virtio/linux/uaccess.h
+++ b/tools/virtio/linux/uaccess.h
@@ -1,8 +1,9 @@
1#ifndef UACCESS_H 1#ifndef UACCESS_H
2#define UACCESS_H 2#define UACCESS_H
3extern void *__user_addr_min, *__user_addr_max;
4 3
5#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) 4#include <linux/compiler.h>
5
6extern void *__user_addr_min, *__user_addr_max;
6 7
7static inline void __chk_user_ptr(const volatile void *p, size_t size) 8static inline void __chk_user_ptr(const volatile void *p, size_t size)
8{ 9{
@@ -13,7 +14,7 @@ static inline void __chk_user_ptr(const volatile void *p, size_t size)
13({ \ 14({ \
14 typeof(ptr) __pu_ptr = (ptr); \ 15 typeof(ptr) __pu_ptr = (ptr); \
15 __chk_user_ptr(__pu_ptr, sizeof(*__pu_ptr)); \ 16 __chk_user_ptr(__pu_ptr, sizeof(*__pu_ptr)); \
16 ACCESS_ONCE(*(__pu_ptr)) = x; \ 17 WRITE_ONCE(*(__pu_ptr), x); \
17 0; \ 18 0; \
18}) 19})
19 20
@@ -21,7 +22,7 @@ static inline void __chk_user_ptr(const volatile void *p, size_t size)
21({ \ 22({ \
22 typeof(ptr) __pu_ptr = (ptr); \ 23 typeof(ptr) __pu_ptr = (ptr); \
23 __chk_user_ptr(__pu_ptr, sizeof(*__pu_ptr)); \ 24 __chk_user_ptr(__pu_ptr, sizeof(*__pu_ptr)); \
24 x = ACCESS_ONCE(*(__pu_ptr)); \ 25 x = READ_ONCE(*(__pu_ptr)); \
25 0; \ 26 0; \
26}) 27})
27 28