aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile50
-rw-r--r--tools/build/feature/test-all.c5
-rw-r--r--tools/build/feature/test-bpf.c20
-rw-r--r--tools/hv/hv_fcopy_daemon.c24
-rw-r--r--tools/hv/hv_vss_daemon.c2
-rw-r--r--tools/include/linux/list.h753
-rw-r--r--tools/lib/bpf/Makefile18
-rw-r--r--tools/lib/bpf/bpf.c4
-rw-r--r--tools/lib/lockdep/Makefile2
-rw-r--r--tools/lib/subcmd/parse-options.h4
-rw-r--r--tools/perf/Build1
-rw-r--r--tools/perf/Documentation/perf-record.txt3
-rw-r--r--tools/perf/Documentation/tips.txt15
-rw-r--r--tools/perf/MANIFEST2
-rw-r--r--tools/perf/builtin-record.c26
-rw-r--r--tools/perf/builtin-report.c10
-rw-r--r--tools/perf/builtin-stat.c8
-rw-r--r--tools/perf/config/Makefile7
-rw-r--r--tools/perf/tests/hists_common.c5
-rw-r--r--tools/perf/tests/hists_cumulate.c1
-rw-r--r--tools/perf/tests/hists_filter.c1
-rw-r--r--tools/perf/tests/hists_link.c1
-rw-r--r--tools/perf/tests/hists_output.c1
-rw-r--r--tools/perf/tests/make18
-rw-r--r--tools/perf/ui/browsers/hists.c2
-rw-r--r--tools/perf/util/event.c4
-rw-r--r--tools/perf/util/strlist.c8
-rw-r--r--tools/perf/util/strlist.h9
-rw-r--r--tools/perf/util/util.c11
-rw-r--r--tools/scripts/Makefile.arch (renamed from tools/perf/config/Makefile.arch)0
-rw-r--r--tools/spi/.gitignore2
-rw-r--r--tools/spi/Makefile4
-rw-r--r--tools/spi/spidev_fdx.c158
-rw-r--r--tools/spi/spidev_test.c399
-rw-r--r--tools/testing/nvdimm/Kbuild2
-rw-r--r--tools/testing/nvdimm/test/iomap.c93
-rw-r--r--tools/testing/nvdimm/test/nfit.c11
-rw-r--r--tools/testing/selftests/Makefile2
-rw-r--r--tools/testing/selftests/breakpoints/.gitignore1
-rw-r--r--tools/testing/selftests/capabilities/Makefile21
-rwxr-xr-xtools/testing/selftests/firmware/fw_filesystem.sh29
-rw-r--r--tools/testing/selftests/intel_pstate/Makefile15
-rw-r--r--tools/testing/selftests/intel_pstate/aperf.c80
-rw-r--r--tools/testing/selftests/intel_pstate/msr.c39
-rwxr-xr-xtools/testing/selftests/intel_pstate/run.sh113
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/.gitignore1
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/Makefile5
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/context_switch.c466
-rw-r--r--tools/testing/selftests/powerpc/dscr/dscr_inherit_exec_test.c8
-rw-r--r--tools/testing/selftests/powerpc/dscr/dscr_inherit_test.c8
-rw-r--r--tools/testing/selftests/powerpc/harness.c43
-rw-r--r--tools/testing/selftests/powerpc/pmu/Makefile4
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/Makefile3
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/ebb.c3
-rw-r--r--tools/testing/selftests/powerpc/pmu/lib.c26
-rw-r--r--tools/testing/selftests/powerpc/pmu/lib.h1
-rwxr-xr-xtools/testing/selftests/powerpc/scripts/hmi.sh89
-rw-r--r--tools/testing/selftests/powerpc/tm/.gitignore3
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile4
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-resched-dscr.c3
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-msr-resv.c74
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-stack.c76
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-syscall.c13
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-vmxcopy.c103
-rw-r--r--tools/testing/selftests/powerpc/tm/tm.h34
-rw-r--r--tools/testing/selftests/powerpc/utils.c87
-rw-r--r--tools/testing/selftests/powerpc/utils.h7
-rw-r--r--tools/testing/selftests/ptrace/.gitignore1
-rw-r--r--tools/testing/selftests/seccomp/test_harness.h5
-rw-r--r--tools/testing/selftests/timers/.gitignore1
-rw-r--r--tools/testing/selftests/vm/.gitignore5
-rw-r--r--tools/testing/selftests/x86/Makefile6
-rw-r--r--tools/testing/selftests/x86/vdso_restorer.c88
73 files changed, 2921 insertions, 230 deletions
diff --git a/tools/Makefile b/tools/Makefile
index 0ba0df3b516f..6339f6ac3ccb 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -8,23 +8,24 @@ include scripts/Makefile.include
8help: 8help:
9 @echo 'Possible targets:' 9 @echo 'Possible targets:'
10 @echo '' 10 @echo ''
11 @echo ' acpi - ACPI tools' 11 @echo ' acpi - ACPI tools'
12 @echo ' cgroup - cgroup tools' 12 @echo ' cgroup - cgroup tools'
13 @echo ' cpupower - a tool for all things x86 CPU power' 13 @echo ' cpupower - a tool for all things x86 CPU power'
14 @echo ' firewire - the userspace part of nosy, an IEEE-1394 traffic sniffer' 14 @echo ' firewire - the userspace part of nosy, an IEEE-1394 traffic sniffer'
15 @echo ' hv - tools used when in Hyper-V clients' 15 @echo ' freefall - laptop accelerometer program for disk protection'
16 @echo ' iio - IIO tools' 16 @echo ' hv - tools used when in Hyper-V clients'
17 @echo ' lguest - a minimal 32-bit x86 hypervisor' 17 @echo ' iio - IIO tools'
18 @echo ' perf - Linux performance measurement and analysis tool' 18 @echo ' lguest - a minimal 32-bit x86 hypervisor'
19 @echo ' selftests - various kernel selftests' 19 @echo ' net - misc networking tools'
20 @echo ' turbostat - Intel CPU idle stats and freq reporting tool' 20 @echo ' perf - Linux performance measurement and analysis tool'
21 @echo ' usb - USB testing tools' 21 @echo ' selftests - various kernel selftests'
22 @echo ' virtio - vhost test module' 22 @echo ' spi - spi tools'
23 @echo ' net - misc networking tools' 23 @echo ' tmon - thermal monitoring and tuning tool'
24 @echo ' vm - misc vm tools' 24 @echo ' turbostat - Intel CPU idle stats and freq reporting tool'
25 @echo ' usb - USB testing tools'
26 @echo ' virtio - vhost test module'
27 @echo ' vm - misc vm tools'
25 @echo ' x86_energy_perf_policy - Intel energy policy tool' 28 @echo ' x86_energy_perf_policy - Intel energy policy tool'
26 @echo ' tmon - thermal monitoring and tuning tool'
27 @echo ' freefall - laptop accelerometer program for disk protection'
28 @echo '' 29 @echo ''
29 @echo 'You can do:' 30 @echo 'You can do:'
30 @echo ' $$ make -C tools/ <tool>_install' 31 @echo ' $$ make -C tools/ <tool>_install'
@@ -52,7 +53,7 @@ acpi: FORCE
52cpupower: FORCE 53cpupower: FORCE
53 $(call descend,power/$@) 54 $(call descend,power/$@)
54 55
55cgroup firewire hv guest usb virtio vm net iio: FORCE 56cgroup firewire hv guest spi usb virtio vm net iio: FORCE
56 $(call descend,$@) 57 $(call descend,$@)
57 58
58liblockdep: FORCE 59liblockdep: FORCE
@@ -118,7 +119,7 @@ acpi_clean:
118cpupower_clean: 119cpupower_clean:
119 $(call descend,power/cpupower,clean) 120 $(call descend,power/cpupower,clean)
120 121
121cgroup_clean hv_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clean net_clean iio_clean: 122cgroup_clean hv_clean firewire_clean lguest_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean:
122 $(call descend,$(@:_clean=),clean) 123 $(call descend,$(@:_clean=),clean)
123 124
124liblockdep_clean: 125liblockdep_clean:
@@ -127,6 +128,12 @@ liblockdep_clean:
127libapi_clean: 128libapi_clean:
128 $(call descend,lib/api,clean) 129 $(call descend,lib/api,clean)
129 130
131libbpf_clean:
132 $(call descend,lib/bpf,clean)
133
134libsubcmd_clean:
135 $(call descend,lib/subcmd,clean)
136
130perf_clean: 137perf_clean:
131 $(call descend,$(@:_clean=),clean) 138 $(call descend,$(@:_clean=),clean)
132 139
@@ -142,9 +149,12 @@ tmon_clean:
142freefall_clean: 149freefall_clean:
143 $(call descend,laptop/freefall,clean) 150 $(call descend,laptop/freefall,clean)
144 151
152build_clean:
153 $(call descend,build,clean)
154
145clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean lguest_clean \ 155clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean lguest_clean \
146 perf_clean selftests_clean turbostat_clean usb_clean virtio_clean \ 156 perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \
147 vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ 157 vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
148 freefall_clean 158 freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean
149 159
150.PHONY: FORCE 160.PHONY: FORCE
diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c
index 33cf6f20bd4e..81025cade45f 100644
--- a/tools/build/feature/test-all.c
+++ b/tools/build/feature/test-all.c
@@ -125,6 +125,10 @@
125# include "test-get_cpuid.c" 125# include "test-get_cpuid.c"
126#undef main 126#undef main
127 127
128#define main main_test_bpf
129# include "test-bpf.c"
130#undef main
131
128int main(int argc, char *argv[]) 132int main(int argc, char *argv[])
129{ 133{
130 main_test_libpython(); 134 main_test_libpython();
@@ -153,6 +157,7 @@ int main(int argc, char *argv[])
153 main_test_pthread_attr_setaffinity_np(); 157 main_test_pthread_attr_setaffinity_np();
154 main_test_lzma(); 158 main_test_lzma();
155 main_test_get_cpuid(); 159 main_test_get_cpuid();
160 main_test_bpf();
156 161
157 return 0; 162 return 0;
158} 163}
diff --git a/tools/build/feature/test-bpf.c b/tools/build/feature/test-bpf.c
index 062bac811af9..b389026839b9 100644
--- a/tools/build/feature/test-bpf.c
+++ b/tools/build/feature/test-bpf.c
@@ -1,9 +1,23 @@
1#include <asm/unistd.h>
1#include <linux/bpf.h> 2#include <linux/bpf.h>
3#include <unistd.h>
4
5#ifndef __NR_bpf
6# if defined(__i386__)
7# define __NR_bpf 357
8# elif defined(__x86_64__)
9# define __NR_bpf 321
10# elif defined(__aarch64__)
11# define __NR_bpf 280
12# error __NR_bpf not defined. libbpf does not support your arch.
13# endif
14#endif
2 15
3int main(void) 16int main(void)
4{ 17{
5 union bpf_attr attr; 18 union bpf_attr attr;
6 19
20 /* Check fields in attr */
7 attr.prog_type = BPF_PROG_TYPE_KPROBE; 21 attr.prog_type = BPF_PROG_TYPE_KPROBE;
8 attr.insn_cnt = 0; 22 attr.insn_cnt = 0;
9 attr.insns = 0; 23 attr.insns = 0;
@@ -14,5 +28,9 @@ int main(void)
14 attr.kern_version = 0; 28 attr.kern_version = 0;
15 29
16 attr = attr; 30 attr = attr;
17 return 0; 31 /*
32 * Test existence of __NR_bpf and BPF_PROG_LOAD.
33 * This call should fail if we run the testcase.
34 */
35 return syscall(__NR_bpf, BPF_PROG_LOAD, attr, sizeof(attr));
18} 36}
diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c
index 5480e4e424eb..fdc9ca4c0356 100644
--- a/tools/hv/hv_fcopy_daemon.c
+++ b/tools/hv/hv_fcopy_daemon.c
@@ -37,12 +37,14 @@
37 37
38static int target_fd; 38static int target_fd;
39static char target_fname[W_MAX_PATH]; 39static char target_fname[W_MAX_PATH];
40static unsigned long long filesize;
40 41
41static int hv_start_fcopy(struct hv_start_fcopy *smsg) 42static int hv_start_fcopy(struct hv_start_fcopy *smsg)
42{ 43{
43 int error = HV_E_FAIL; 44 int error = HV_E_FAIL;
44 char *q, *p; 45 char *q, *p;
45 46
47 filesize = 0;
46 p = (char *)smsg->path_name; 48 p = (char *)smsg->path_name;
47 snprintf(target_fname, sizeof(target_fname), "%s/%s", 49 snprintf(target_fname, sizeof(target_fname), "%s/%s",
48 (char *)smsg->path_name, (char *)smsg->file_name); 50 (char *)smsg->path_name, (char *)smsg->file_name);
@@ -98,14 +100,26 @@ done:
98static int hv_copy_data(struct hv_do_fcopy *cpmsg) 100static int hv_copy_data(struct hv_do_fcopy *cpmsg)
99{ 101{
100 ssize_t bytes_written; 102 ssize_t bytes_written;
103 int ret = 0;
101 104
102 bytes_written = pwrite(target_fd, cpmsg->data, cpmsg->size, 105 bytes_written = pwrite(target_fd, cpmsg->data, cpmsg->size,
103 cpmsg->offset); 106 cpmsg->offset);
104 107
105 if (bytes_written != cpmsg->size) 108 filesize += cpmsg->size;
106 return HV_E_FAIL; 109 if (bytes_written != cpmsg->size) {
110 switch (errno) {
111 case ENOSPC:
112 ret = HV_ERROR_DISK_FULL;
113 break;
114 default:
115 ret = HV_E_FAIL;
116 break;
117 }
118 syslog(LOG_ERR, "pwrite failed to write %llu bytes: %ld (%s)",
119 filesize, (long)bytes_written, strerror(errno));
120 }
107 121
108 return 0; 122 return ret;
109} 123}
110 124
111static int hv_copy_finished(void) 125static int hv_copy_finished(void)
@@ -165,7 +179,7 @@ int main(int argc, char *argv[])
165 } 179 }
166 180
167 openlog("HV_FCOPY", 0, LOG_USER); 181 openlog("HV_FCOPY", 0, LOG_USER);
168 syslog(LOG_INFO, "HV_FCOPY starting; pid is:%d", getpid()); 182 syslog(LOG_INFO, "starting; pid is:%d", getpid());
169 183
170 fcopy_fd = open("/dev/vmbus/hv_fcopy", O_RDWR); 184 fcopy_fd = open("/dev/vmbus/hv_fcopy", O_RDWR);
171 185
@@ -201,7 +215,7 @@ int main(int argc, char *argv[])
201 } 215 }
202 kernel_modver = *(__u32 *)buffer; 216 kernel_modver = *(__u32 *)buffer;
203 in_handshake = 0; 217 in_handshake = 0;
204 syslog(LOG_INFO, "HV_FCOPY: kernel module version: %d", 218 syslog(LOG_INFO, "kernel module version: %d",
205 kernel_modver); 219 kernel_modver);
206 continue; 220 continue;
207 } 221 }
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
index 96234b638249..5d51d6ff08e6 100644
--- a/tools/hv/hv_vss_daemon.c
+++ b/tools/hv/hv_vss_daemon.c
@@ -254,7 +254,7 @@ int main(int argc, char *argv[])
254 syslog(LOG_ERR, "Illegal op:%d\n", op); 254 syslog(LOG_ERR, "Illegal op:%d\n", op);
255 } 255 }
256 vss_msg->error = error; 256 vss_msg->error = error;
257 len = write(vss_fd, &error, sizeof(struct hv_vss_msg)); 257 len = write(vss_fd, vss_msg, sizeof(struct hv_vss_msg));
258 if (len != sizeof(struct hv_vss_msg)) { 258 if (len != sizeof(struct hv_vss_msg)) {
259 syslog(LOG_ERR, "write failed; error: %d %s", errno, 259 syslog(LOG_ERR, "write failed; error: %d %s", errno,
260 strerror(errno)); 260 strerror(errno));
diff --git a/tools/include/linux/list.h b/tools/include/linux/list.h
index a017f1595676..1da423820ad4 100644
--- a/tools/include/linux/list.h
+++ b/tools/include/linux/list.h
@@ -1,11 +1,751 @@
1#include <linux/compiler.h> 1#ifndef __TOOLS_LINUX_LIST_H
2#include <linux/kernel.h> 2#define __TOOLS_LINUX_LIST_H
3
3#include <linux/types.h> 4#include <linux/types.h>
5#include <linux/poison.h>
6#include <linux/kernel.h>
7#include <linux/compiler.h>
8
9/*
10 * Simple doubly linked list implementation.
11 *
12 * Some of the internal functions ("__xxx") are useful when
13 * manipulating whole lists rather than single entries, as
14 * sometimes we already know the next/prev entries and we can
15 * generate better code by using them directly rather than
16 * using the generic single-entry routines.
17 */
18
19#define LIST_HEAD_INIT(name) { &(name), &(name) }
20
21#define LIST_HEAD(name) \
22 struct list_head name = LIST_HEAD_INIT(name)
23
24static inline void INIT_LIST_HEAD(struct list_head *list)
25{
26 list->next = list;
27 list->prev = list;
28}
29
30/*
31 * Insert a new entry between two known consecutive entries.
32 *
33 * This is only for internal list manipulation where we know
34 * the prev/next entries already!
35 */
36#ifndef CONFIG_DEBUG_LIST
37static inline void __list_add(struct list_head *new,
38 struct list_head *prev,
39 struct list_head *next)
40{
41 next->prev = new;
42 new->next = next;
43 new->prev = prev;
44 prev->next = new;
45}
46#else
47extern void __list_add(struct list_head *new,
48 struct list_head *prev,
49 struct list_head *next);
50#endif
51
52/**
53 * list_add - add a new entry
54 * @new: new entry to be added
55 * @head: list head to add it after
56 *
57 * Insert a new entry after the specified head.
58 * This is good for implementing stacks.
59 */
60static inline void list_add(struct list_head *new, struct list_head *head)
61{
62 __list_add(new, head, head->next);
63}
64
65
66/**
67 * list_add_tail - add a new entry
68 * @new: new entry to be added
69 * @head: list head to add it before
70 *
71 * Insert a new entry before the specified head.
72 * This is useful for implementing queues.
73 */
74static inline void list_add_tail(struct list_head *new, struct list_head *head)
75{
76 __list_add(new, head->prev, head);
77}
78
79/*
80 * Delete a list entry by making the prev/next entries
81 * point to each other.
82 *
83 * This is only for internal list manipulation where we know
84 * the prev/next entries already!
85 */
86static inline void __list_del(struct list_head * prev, struct list_head * next)
87{
88 next->prev = prev;
89 WRITE_ONCE(prev->next, next);
90}
91
92/**
93 * list_del - deletes entry from list.
94 * @entry: the element to delete from the list.
95 * Note: list_empty() on entry does not return true after this, the entry is
96 * in an undefined state.
97 */
98#ifndef CONFIG_DEBUG_LIST
99static inline void __list_del_entry(struct list_head *entry)
100{
101 __list_del(entry->prev, entry->next);
102}
103
104static inline void list_del(struct list_head *entry)
105{
106 __list_del(entry->prev, entry->next);
107 entry->next = LIST_POISON1;
108 entry->prev = LIST_POISON2;
109}
110#else
111extern void __list_del_entry(struct list_head *entry);
112extern void list_del(struct list_head *entry);
113#endif
114
115/**
116 * list_replace - replace old entry by new one
117 * @old : the element to be replaced
118 * @new : the new element to insert
119 *
120 * If @old was empty, it will be overwritten.
121 */
122static inline void list_replace(struct list_head *old,
123 struct list_head *new)
124{
125 new->next = old->next;
126 new->next->prev = new;
127 new->prev = old->prev;
128 new->prev->next = new;
129}
130
131static inline void list_replace_init(struct list_head *old,
132 struct list_head *new)
133{
134 list_replace(old, new);
135 INIT_LIST_HEAD(old);
136}
137
138/**
139 * list_del_init - deletes entry from list and reinitialize it.
140 * @entry: the element to delete from the list.
141 */
142static inline void list_del_init(struct list_head *entry)
143{
144 __list_del_entry(entry);
145 INIT_LIST_HEAD(entry);
146}
147
148/**
149 * list_move - delete from one list and add as another's head
150 * @list: the entry to move
151 * @head: the head that will precede our entry
152 */
153static inline void list_move(struct list_head *list, struct list_head *head)
154{
155 __list_del_entry(list);
156 list_add(list, head);
157}
158
159/**
160 * list_move_tail - delete from one list and add as another's tail
161 * @list: the entry to move
162 * @head: the head that will follow our entry
163 */
164static inline void list_move_tail(struct list_head *list,
165 struct list_head *head)
166{
167 __list_del_entry(list);
168 list_add_tail(list, head);
169}
170
171/**
172 * list_is_last - tests whether @list is the last entry in list @head
173 * @list: the entry to test
174 * @head: the head of the list
175 */
176static inline int list_is_last(const struct list_head *list,
177 const struct list_head *head)
178{
179 return list->next == head;
180}
181
182/**
183 * list_empty - tests whether a list is empty
184 * @head: the list to test.
185 */
186static inline int list_empty(const struct list_head *head)
187{
188 return head->next == head;
189}
190
191/**
192 * list_empty_careful - tests whether a list is empty and not being modified
193 * @head: the list to test
194 *
195 * Description:
196 * tests whether a list is empty _and_ checks that no other CPU might be
197 * in the process of modifying either member (next or prev)
198 *
199 * NOTE: using list_empty_careful() without synchronization
200 * can only be safe if the only activity that can happen
201 * to the list entry is list_del_init(). Eg. it cannot be used
202 * if another CPU could re-list_add() it.
203 */
204static inline int list_empty_careful(const struct list_head *head)
205{
206 struct list_head *next = head->next;
207 return (next == head) && (next == head->prev);
208}
209
210/**
211 * list_rotate_left - rotate the list to the left
212 * @head: the head of the list
213 */
214static inline void list_rotate_left(struct list_head *head)
215{
216 struct list_head *first;
217
218 if (!list_empty(head)) {
219 first = head->next;
220 list_move_tail(first, head);
221 }
222}
223
224/**
225 * list_is_singular - tests whether a list has just one entry.
226 * @head: the list to test.
227 */
228static inline int list_is_singular(const struct list_head *head)
229{
230 return !list_empty(head) && (head->next == head->prev);
231}
232
233static inline void __list_cut_position(struct list_head *list,
234 struct list_head *head, struct list_head *entry)
235{
236 struct list_head *new_first = entry->next;
237 list->next = head->next;
238 list->next->prev = list;
239 list->prev = entry;
240 entry->next = list;
241 head->next = new_first;
242 new_first->prev = head;
243}
244
245/**
246 * list_cut_position - cut a list into two
247 * @list: a new list to add all removed entries
248 * @head: a list with entries
249 * @entry: an entry within head, could be the head itself
250 * and if so we won't cut the list
251 *
252 * This helper moves the initial part of @head, up to and
253 * including @entry, from @head to @list. You should
254 * pass on @entry an element you know is on @head. @list
255 * should be an empty list or a list you do not care about
256 * losing its data.
257 *
258 */
259static inline void list_cut_position(struct list_head *list,
260 struct list_head *head, struct list_head *entry)
261{
262 if (list_empty(head))
263 return;
264 if (list_is_singular(head) &&
265 (head->next != entry && head != entry))
266 return;
267 if (entry == head)
268 INIT_LIST_HEAD(list);
269 else
270 __list_cut_position(list, head, entry);
271}
272
273static inline void __list_splice(const struct list_head *list,
274 struct list_head *prev,
275 struct list_head *next)
276{
277 struct list_head *first = list->next;
278 struct list_head *last = list->prev;
279
280 first->prev = prev;
281 prev->next = first;
282
283 last->next = next;
284 next->prev = last;
285}
286
287/**
288 * list_splice - join two lists, this is designed for stacks
289 * @list: the new list to add.
290 * @head: the place to add it in the first list.
291 */
292static inline void list_splice(const struct list_head *list,
293 struct list_head *head)
294{
295 if (!list_empty(list))
296 __list_splice(list, head, head->next);
297}
298
299/**
300 * list_splice_tail - join two lists, each list being a queue
301 * @list: the new list to add.
302 * @head: the place to add it in the first list.
303 */
304static inline void list_splice_tail(struct list_head *list,
305 struct list_head *head)
306{
307 if (!list_empty(list))
308 __list_splice(list, head->prev, head);
309}
310
311/**
312 * list_splice_init - join two lists and reinitialise the emptied list.
313 * @list: the new list to add.
314 * @head: the place to add it in the first list.
315 *
316 * The list at @list is reinitialised
317 */
318static inline void list_splice_init(struct list_head *list,
319 struct list_head *head)
320{
321 if (!list_empty(list)) {
322 __list_splice(list, head, head->next);
323 INIT_LIST_HEAD(list);
324 }
325}
326
327/**
328 * list_splice_tail_init - join two lists and reinitialise the emptied list
329 * @list: the new list to add.
330 * @head: the place to add it in the first list.
331 *
332 * Each of the lists is a queue.
333 * The list at @list is reinitialised
334 */
335static inline void list_splice_tail_init(struct list_head *list,
336 struct list_head *head)
337{
338 if (!list_empty(list)) {
339 __list_splice(list, head->prev, head);
340 INIT_LIST_HEAD(list);
341 }
342}
343
344/**
345 * list_entry - get the struct for this entry
346 * @ptr: the &struct list_head pointer.
347 * @type: the type of the struct this is embedded in.
348 * @member: the name of the list_head within the struct.
349 */
350#define list_entry(ptr, type, member) \
351 container_of(ptr, type, member)
352
353/**
354 * list_first_entry - get the first element from a list
355 * @ptr: the list head to take the element from.
356 * @type: the type of the struct this is embedded in.
357 * @member: the name of the list_head within the struct.
358 *
359 * Note, that list is expected to be not empty.
360 */
361#define list_first_entry(ptr, type, member) \
362 list_entry((ptr)->next, type, member)
363
364/**
365 * list_last_entry - get the last element from a list
366 * @ptr: the list head to take the element from.
367 * @type: the type of the struct this is embedded in.
368 * @member: the name of the list_head within the struct.
369 *
370 * Note, that list is expected to be not empty.
371 */
372#define list_last_entry(ptr, type, member) \
373 list_entry((ptr)->prev, type, member)
374
375/**
376 * list_first_entry_or_null - get the first element from a list
377 * @ptr: the list head to take the element from.
378 * @type: the type of the struct this is embedded in.
379 * @member: the name of the list_head within the struct.
380 *
381 * Note that if the list is empty, it returns NULL.
382 */
383#define list_first_entry_or_null(ptr, type, member) \
384 (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
385
386/**
387 * list_next_entry - get the next element in list
388 * @pos: the type * to cursor
389 * @member: the name of the list_head within the struct.
390 */
391#define list_next_entry(pos, member) \
392 list_entry((pos)->member.next, typeof(*(pos)), member)
393
394/**
395 * list_prev_entry - get the prev element in list
396 * @pos: the type * to cursor
397 * @member: the name of the list_head within the struct.
398 */
399#define list_prev_entry(pos, member) \
400 list_entry((pos)->member.prev, typeof(*(pos)), member)
401
402/**
403 * list_for_each - iterate over a list
404 * @pos: the &struct list_head to use as a loop cursor.
405 * @head: the head for your list.
406 */
407#define list_for_each(pos, head) \
408 for (pos = (head)->next; pos != (head); pos = pos->next)
409
410/**
411 * list_for_each_prev - iterate over a list backwards
412 * @pos: the &struct list_head to use as a loop cursor.
413 * @head: the head for your list.
414 */
415#define list_for_each_prev(pos, head) \
416 for (pos = (head)->prev; pos != (head); pos = pos->prev)
417
418/**
419 * list_for_each_safe - iterate over a list safe against removal of list entry
420 * @pos: the &struct list_head to use as a loop cursor.
421 * @n: another &struct list_head to use as temporary storage
422 * @head: the head for your list.
423 */
424#define list_for_each_safe(pos, n, head) \
425 for (pos = (head)->next, n = pos->next; pos != (head); \
426 pos = n, n = pos->next)
427
428/**
429 * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
430 * @pos: the &struct list_head to use as a loop cursor.
431 * @n: another &struct list_head to use as temporary storage
432 * @head: the head for your list.
433 */
434#define list_for_each_prev_safe(pos, n, head) \
435 for (pos = (head)->prev, n = pos->prev; \
436 pos != (head); \
437 pos = n, n = pos->prev)
438
439/**
440 * list_for_each_entry - iterate over list of given type
441 * @pos: the type * to use as a loop cursor.
442 * @head: the head for your list.
443 * @member: the name of the list_head within the struct.
444 */
445#define list_for_each_entry(pos, head, member) \
446 for (pos = list_first_entry(head, typeof(*pos), member); \
447 &pos->member != (head); \
448 pos = list_next_entry(pos, member))
449
450/**
451 * list_for_each_entry_reverse - iterate backwards over list of given type.
452 * @pos: the type * to use as a loop cursor.
453 * @head: the head for your list.
454 * @member: the name of the list_head within the struct.
455 */
456#define list_for_each_entry_reverse(pos, head, member) \
457 for (pos = list_last_entry(head, typeof(*pos), member); \
458 &pos->member != (head); \
459 pos = list_prev_entry(pos, member))
460
461/**
462 * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
463 * @pos: the type * to use as a start point
464 * @head: the head of the list
465 * @member: the name of the list_head within the struct.
466 *
467 * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
468 */
469#define list_prepare_entry(pos, head, member) \
470 ((pos) ? : list_entry(head, typeof(*pos), member))
471
472/**
473 * list_for_each_entry_continue - continue iteration over list of given type
474 * @pos: the type * to use as a loop cursor.
475 * @head: the head for your list.
476 * @member: the name of the list_head within the struct.
477 *
478 * Continue to iterate over list of given type, continuing after
479 * the current position.
480 */
481#define list_for_each_entry_continue(pos, head, member) \
482 for (pos = list_next_entry(pos, member); \
483 &pos->member != (head); \
484 pos = list_next_entry(pos, member))
485
486/**
487 * list_for_each_entry_continue_reverse - iterate backwards from the given point
488 * @pos: the type * to use as a loop cursor.
489 * @head: the head for your list.
490 * @member: the name of the list_head within the struct.
491 *
492 * Start to iterate over list of given type backwards, continuing after
493 * the current position.
494 */
495#define list_for_each_entry_continue_reverse(pos, head, member) \
496 for (pos = list_prev_entry(pos, member); \
497 &pos->member != (head); \
498 pos = list_prev_entry(pos, member))
499
500/**
501 * list_for_each_entry_from - iterate over list of given type from the current point
502 * @pos: the type * to use as a loop cursor.
503 * @head: the head for your list.
504 * @member: the name of the list_head within the struct.
505 *
506 * Iterate over list of given type, continuing from current position.
507 */
508#define list_for_each_entry_from(pos, head, member) \
509 for (; &pos->member != (head); \
510 pos = list_next_entry(pos, member))
511
512/**
513 * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
514 * @pos: the type * to use as a loop cursor.
515 * @n: another type * to use as temporary storage
516 * @head: the head for your list.
517 * @member: the name of the list_head within the struct.
518 */
519#define list_for_each_entry_safe(pos, n, head, member) \
520 for (pos = list_first_entry(head, typeof(*pos), member), \
521 n = list_next_entry(pos, member); \
522 &pos->member != (head); \
523 pos = n, n = list_next_entry(n, member))
524
525/**
526 * list_for_each_entry_safe_continue - continue list iteration safe against removal
527 * @pos: the type * to use as a loop cursor.
528 * @n: another type * to use as temporary storage
529 * @head: the head for your list.
530 * @member: the name of the list_head within the struct.
531 *
532 * Iterate over list of given type, continuing after current point,
533 * safe against removal of list entry.
534 */
535#define list_for_each_entry_safe_continue(pos, n, head, member) \
536 for (pos = list_next_entry(pos, member), \
537 n = list_next_entry(pos, member); \
538 &pos->member != (head); \
539 pos = n, n = list_next_entry(n, member))
540
541/**
542 * list_for_each_entry_safe_from - iterate over list from current point safe against removal
543 * @pos: the type * to use as a loop cursor.
544 * @n: another type * to use as temporary storage
545 * @head: the head for your list.
546 * @member: the name of the list_head within the struct.
547 *
548 * Iterate over list of given type from current point, safe against
549 * removal of list entry.
550 */
551#define list_for_each_entry_safe_from(pos, n, head, member) \
552 for (n = list_next_entry(pos, member); \
553 &pos->member != (head); \
554 pos = n, n = list_next_entry(n, member))
555
556/**
557 * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
558 * @pos: the type * to use as a loop cursor.
559 * @n: another type * to use as temporary storage
560 * @head: the head for your list.
561 * @member: the name of the list_head within the struct.
562 *
563 * Iterate backwards over list of given type, safe against removal
564 * of list entry.
565 */
566#define list_for_each_entry_safe_reverse(pos, n, head, member) \
567 for (pos = list_last_entry(head, typeof(*pos), member), \
568 n = list_prev_entry(pos, member); \
569 &pos->member != (head); \
570 pos = n, n = list_prev_entry(n, member))
4 571
5#include "../../../include/linux/list.h" 572/**
573 * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
574 * @pos: the loop cursor used in the list_for_each_entry_safe loop
575 * @n: temporary storage used in list_for_each_entry_safe
576 * @member: the name of the list_head within the struct.
577 *
578 * list_safe_reset_next is not safe to use in general if the list may be
579 * modified concurrently (eg. the lock is dropped in the loop body). An
580 * exception to this is if the cursor element (pos) is pinned in the list,
581 * and list_safe_reset_next is called after re-taking the lock and before
582 * completing the current iteration of the loop body.
583 */
584#define list_safe_reset_next(pos, n, member) \
585 n = list_next_entry(pos, member)
586
587/*
588 * Double linked lists with a single pointer list head.
589 * Mostly useful for hash tables where the two pointer list head is
590 * too wasteful.
591 * You lose the ability to access the tail in O(1).
592 */
593
594#define HLIST_HEAD_INIT { .first = NULL }
595#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
596#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
597static inline void INIT_HLIST_NODE(struct hlist_node *h)
598{
599 h->next = NULL;
600 h->pprev = NULL;
601}
602
603static inline int hlist_unhashed(const struct hlist_node *h)
604{
605 return !h->pprev;
606}
607
608static inline int hlist_empty(const struct hlist_head *h)
609{
610 return !h->first;
611}
612
613static inline void __hlist_del(struct hlist_node *n)
614{
615 struct hlist_node *next = n->next;
616 struct hlist_node **pprev = n->pprev;
617
618 WRITE_ONCE(*pprev, next);
619 if (next)
620 next->pprev = pprev;
621}
622
623static inline void hlist_del(struct hlist_node *n)
624{
625 __hlist_del(n);
626 n->next = LIST_POISON1;
627 n->pprev = LIST_POISON2;
628}
629
630static inline void hlist_del_init(struct hlist_node *n)
631{
632 if (!hlist_unhashed(n)) {
633 __hlist_del(n);
634 INIT_HLIST_NODE(n);
635 }
636}
637
638static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
639{
640 struct hlist_node *first = h->first;
641 n->next = first;
642 if (first)
643 first->pprev = &n->next;
644 h->first = n;
645 n->pprev = &h->first;
646}
647
648/* next must be != NULL */
649static inline void hlist_add_before(struct hlist_node *n,
650 struct hlist_node *next)
651{
652 n->pprev = next->pprev;
653 n->next = next;
654 next->pprev = &n->next;
655 *(n->pprev) = n;
656}
657
658static inline void hlist_add_behind(struct hlist_node *n,
659 struct hlist_node *prev)
660{
661 n->next = prev->next;
662 prev->next = n;
663 n->pprev = &prev->next;
664
665 if (n->next)
666 n->next->pprev = &n->next;
667}
668
669/* after that we'll appear to be on some hlist and hlist_del will work */
670static inline void hlist_add_fake(struct hlist_node *n)
671{
672 n->pprev = &n->next;
673}
674
675static inline bool hlist_fake(struct hlist_node *h)
676{
677 return h->pprev == &h->next;
678}
679
680/*
681 * Move a list from one list head to another. Fixup the pprev
682 * reference of the first entry if it exists.
683 */
684static inline void hlist_move_list(struct hlist_head *old,
685 struct hlist_head *new)
686{
687 new->first = old->first;
688 if (new->first)
689 new->first->pprev = &new->first;
690 old->first = NULL;
691}
692
693#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
694
695#define hlist_for_each(pos, head) \
696 for (pos = (head)->first; pos ; pos = pos->next)
697
698#define hlist_for_each_safe(pos, n, head) \
699 for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
700 pos = n)
701
702#define hlist_entry_safe(ptr, type, member) \
703 ({ typeof(ptr) ____ptr = (ptr); \
704 ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
705 })
706
707/**
708 * hlist_for_each_entry - iterate over list of given type
709 * @pos: the type * to use as a loop cursor.
710 * @head: the head for your list.
711 * @member: the name of the hlist_node within the struct.
712 */
713#define hlist_for_each_entry(pos, head, member) \
714 for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
715 pos; \
716 pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
717
718/**
719 * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
720 * @pos: the type * to use as a loop cursor.
721 * @member: the name of the hlist_node within the struct.
722 */
723#define hlist_for_each_entry_continue(pos, member) \
724 for (pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member);\
725 pos; \
726 pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
727
728/**
729 * hlist_for_each_entry_from - iterate over a hlist continuing from current point
730 * @pos: the type * to use as a loop cursor.
731 * @member: the name of the hlist_node within the struct.
732 */
733#define hlist_for_each_entry_from(pos, member) \
734 for (; pos; \
735 pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
736
737/**
738 * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
739 * @pos: the type * to use as a loop cursor.
740 * @n: another &struct hlist_node to use as temporary storage
741 * @head: the head for your list.
742 * @member: the name of the hlist_node within the struct.
743 */
744#define hlist_for_each_entry_safe(pos, n, head, member) \
745 for (pos = hlist_entry_safe((head)->first, typeof(*pos), member);\
746 pos && ({ n = pos->member.next; 1; }); \
747 pos = hlist_entry_safe(n, typeof(*pos), member))
6 748
7#ifndef TOOLS_LIST_H
8#define TOOLS_LIST_H
9/** 749/**
10 * list_del_range - deletes range of entries from list. 750 * list_del_range - deletes range of entries from list.
11 * @begin: first element in the range to delete from the list. 751 * @begin: first element in the range to delete from the list.
@@ -27,4 +767,5 @@ static inline void list_del_range(struct list_head *begin,
27 */ 767 */
28#define list_for_each_from(pos, head) \ 768#define list_for_each_from(pos, head) \
29 for (; pos != (head); pos = pos->next) 769 for (; pos != (head); pos = pos->next)
30#endif 770
771#endif /* __TOOLS_LINUX_LIST_H */
diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index 919b71780710..fc1bc75ae56d 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -6,6 +6,12 @@ BPF_EXTRAVERSION = 1
6 6
7MAKEFLAGS += --no-print-directory 7MAKEFLAGS += --no-print-directory
8 8
9ifeq ($(srctree),)
10srctree := $(patsubst %/,%,$(dir $(shell pwd)))
11srctree := $(patsubst %/,%,$(dir $(srctree)))
12srctree := $(patsubst %/,%,$(dir $(srctree)))
13#$(info Determined 'srctree' to be $(srctree))
14endif
9 15
10# Makefiles suck: This macro sets a default value of $(2) for the 16# Makefiles suck: This macro sets a default value of $(2) for the
11# variable named by $(1), unless the variable has been set by 17# variable named by $(1), unless the variable has been set by
@@ -31,7 +37,8 @@ INSTALL = install
31DESTDIR ?= 37DESTDIR ?=
32DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))' 38DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
33 39
34LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) 40include $(srctree)/tools/scripts/Makefile.arch
41
35ifeq ($(LP64), 1) 42ifeq ($(LP64), 1)
36 libdir_relative = lib64 43 libdir_relative = lib64
37else 44else
@@ -57,13 +64,6 @@ ifndef VERBOSE
57 VERBOSE = 0 64 VERBOSE = 0
58endif 65endif
59 66
60ifeq ($(srctree),)
61srctree := $(patsubst %/,%,$(dir $(shell pwd)))
62srctree := $(patsubst %/,%,$(dir $(srctree)))
63srctree := $(patsubst %/,%,$(dir $(srctree)))
64#$(info Determined 'srctree' to be $(srctree))
65endif
66
67FEATURE_USER = .libbpf 67FEATURE_USER = .libbpf
68FEATURE_TESTS = libelf libelf-getphdrnum libelf-mmap bpf 68FEATURE_TESTS = libelf libelf-getphdrnum libelf-mmap bpf
69FEATURE_DISPLAY = libelf bpf 69FEATURE_DISPLAY = libelf bpf
@@ -192,7 +192,7 @@ config-clean:
192 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null 192 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null
193 193
194clean: 194clean:
195 $(call QUIET_CLEAN, libbpf) $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \ 195 $(call QUIET_CLEAN, libbpf) $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d .*.cmd \
196 $(RM) LIBBPF-CFLAGS 196 $(RM) LIBBPF-CFLAGS
197 $(call QUIET_CLEAN, core-gen) $(RM) $(OUTPUT)FEATURE-DUMP.libbpf 197 $(call QUIET_CLEAN, core-gen) $(RM) $(OUTPUT)FEATURE-DUMP.libbpf
198 198
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 5bdc6eab6852..1f91cc941b7c 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -14,8 +14,8 @@
14#include "bpf.h" 14#include "bpf.h"
15 15
16/* 16/*
17 * When building perf, unistd.h is override. Define __NR_bpf is 17 * When building perf, unistd.h is overrided. __NR_bpf is
18 * required to be defined. 18 * required to be defined explicitly.
19 */ 19 */
20#ifndef __NR_bpf 20#ifndef __NR_bpf
21# if defined(__i386__) 21# if defined(__i386__)
diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
index 7e319afac78a..90d2baeb621a 100644
--- a/tools/lib/lockdep/Makefile
+++ b/tools/lib/lockdep/Makefile
@@ -149,7 +149,7 @@ install_lib: all_cmd
149install: install_lib 149install: install_lib
150 150
151clean: 151clean:
152 $(RM) *.o *~ $(TARGETS) *.a *liblockdep*.so* $(VERSION_FILES) .*.d 152 $(RM) *.o *~ $(TARGETS) *.a *liblockdep*.so* $(VERSION_FILES) .*.d .*.cmd
153 $(RM) tags TAGS 153 $(RM) tags TAGS
154 154
155PHONY += force 155PHONY += force
diff --git a/tools/lib/subcmd/parse-options.h b/tools/lib/subcmd/parse-options.h
index 13a2cc1d6140..d60cab2726da 100644
--- a/tools/lib/subcmd/parse-options.h
+++ b/tools/lib/subcmd/parse-options.h
@@ -4,6 +4,10 @@
4#include <stdbool.h> 4#include <stdbool.h>
5#include <stdint.h> 5#include <stdint.h>
6 6
7#ifndef NORETURN
8#define NORETURN __attribute__((__noreturn__))
9#endif
10
7enum parse_opt_type { 11enum parse_opt_type {
8 /* special types */ 12 /* special types */
9 OPTION_END, 13 OPTION_END,
diff --git a/tools/perf/Build b/tools/perf/Build
index 6b67e6f4179f..a43fae7f439a 100644
--- a/tools/perf/Build
+++ b/tools/perf/Build
@@ -42,6 +42,7 @@ CFLAGS_perf.o += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))" \
42 -include $(OUTPUT)PERF-VERSION-FILE 42 -include $(OUTPUT)PERF-VERSION-FILE
43CFLAGS_builtin-trace.o += -DSTRACE_GROUPS_DIR="BUILD_STR($(STRACE_GROUPS_DIR_SQ))" 43CFLAGS_builtin-trace.o += -DSTRACE_GROUPS_DIR="BUILD_STR($(STRACE_GROUPS_DIR_SQ))"
44CFLAGS_builtin-report.o += -DTIPDIR="BUILD_STR($(tipdir_SQ))" 44CFLAGS_builtin-report.o += -DTIPDIR="BUILD_STR($(tipdir_SQ))"
45CFLAGS_builtin-report.o += -DDOCDIR="BUILD_STR($(srcdir_SQ)/Documentation)"
45 46
46libperf-y += util/ 47libperf-y += util/
47libperf-y += arch/ 48libperf-y += arch/
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 3a1a32f5479f..fbceb631387c 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -338,6 +338,9 @@ Options passed to clang when compiling BPF scriptlets.
338Specify vmlinux path which has debuginfo. 338Specify vmlinux path which has debuginfo.
339(enabled when BPF prologue is on) 339(enabled when BPF prologue is on)
340 340
341--buildid-all::
342Record build-id of all DSOs regardless whether it's actually hit or not.
343
341SEE ALSO 344SEE ALSO
342-------- 345--------
343linkperf:perf-stat[1], linkperf:perf-list[1] 346linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/tips.txt b/tools/perf/Documentation/tips.txt
index a1c10e360db5..e0ce9573b79b 100644
--- a/tools/perf/Documentation/tips.txt
+++ b/tools/perf/Documentation/tips.txt
@@ -12,3 +12,18 @@ List events using substring match: perf list <keyword>
12To see list of saved events and attributes: perf evlist -v 12To see list of saved events and attributes: perf evlist -v
13Use --symfs <dir> if your symbol files are in non-standard locations 13Use --symfs <dir> if your symbol files are in non-standard locations
14To see callchains in a more compact form: perf report -g folded 14To see callchains in a more compact form: perf report -g folded
15Show individual samples with: perf script
16Limit to show entries above 5% only: perf report --percent-limit 5
17Profiling branch (mis)predictions with: perf record -b / perf report
18Treat branches as callchains: perf report --branch-history
19To count events in every 1000 msec: perf stat -I 1000
20Print event counts in CSV format with: perf stat -x,
21If you have debuginfo enabled, try: perf report -s sym,srcline
22For memory address profiling, try: perf mem record / perf mem report
23For tracepoint events, try: perf report -s trace_fields
24To record callchains for each sample: perf record -g
25To record every process run by an user: perf record -u <user>
26Skip collecing build-id when recording: perf record -B
27To change sampling frequency to 100 Hz: perf record -F 100
28See assembly instructions with percentage: perf annotate <symbol>
29If you prefer Intel style assembly, try: perf annotate -M intel
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index ddf922f93aa1..2e1fa2357528 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -28,6 +28,7 @@ tools/lib/string.c
28tools/lib/symbol/kallsyms.c 28tools/lib/symbol/kallsyms.c
29tools/lib/symbol/kallsyms.h 29tools/lib/symbol/kallsyms.h
30tools/lib/find_bit.c 30tools/lib/find_bit.c
31tools/lib/bitmap.c
31tools/include/asm/atomic.h 32tools/include/asm/atomic.h
32tools/include/asm/barrier.h 33tools/include/asm/barrier.h
33tools/include/asm/bug.h 34tools/include/asm/bug.h
@@ -57,6 +58,7 @@ tools/include/linux/rbtree_augmented.h
57tools/include/linux/string.h 58tools/include/linux/string.h
58tools/include/linux/types.h 59tools/include/linux/types.h
59tools/include/linux/err.h 60tools/include/linux/err.h
61tools/include/linux/bitmap.h
60include/asm-generic/bitops/arch_hweight.h 62include/asm-generic/bitops/arch_hweight.h
61include/asm-generic/bitops/const_hweight.h 63include/asm-generic/bitops/const_hweight.h
62include/asm-generic/bitops/fls64.h 64include/asm-generic/bitops/fls64.h
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index dc4e0adf5c5b..319712a4e02b 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -50,6 +50,7 @@ struct record {
50 int realtime_prio; 50 int realtime_prio;
51 bool no_buildid; 51 bool no_buildid;
52 bool no_buildid_cache; 52 bool no_buildid_cache;
53 bool buildid_all;
53 unsigned long long samples; 54 unsigned long long samples;
54}; 55};
55 56
@@ -362,6 +363,13 @@ static int process_buildids(struct record *rec)
362 */ 363 */
363 symbol_conf.ignore_vmlinux_buildid = true; 364 symbol_conf.ignore_vmlinux_buildid = true;
364 365
366 /*
367 * If --buildid-all is given, it marks all DSO regardless of hits,
368 * so no need to process samples.
369 */
370 if (rec->buildid_all)
371 rec->tool.sample = NULL;
372
365 return perf_session__process_events(session); 373 return perf_session__process_events(session);
366} 374}
367 375
@@ -756,12 +764,8 @@ out_child:
756 764
757 if (!rec->no_buildid) { 765 if (!rec->no_buildid) {
758 process_buildids(rec); 766 process_buildids(rec);
759 /* 767
760 * We take all buildids when the file contains 768 if (rec->buildid_all)
761 * AUX area tracing data because we do not decode the
762 * trace because it would take too long.
763 */
764 if (rec->opts.full_auxtrace)
765 dsos__hit_all(rec->session); 769 dsos__hit_all(rec->session);
766 } 770 }
767 perf_session__write_header(rec->session, rec->evlist, fd, true); 771 perf_session__write_header(rec->session, rec->evlist, fd, true);
@@ -1138,6 +1142,8 @@ struct option __record_options[] = {
1138 "options passed to clang when compiling BPF scriptlets"), 1142 "options passed to clang when compiling BPF scriptlets"),
1139 OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 1143 OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
1140 "file", "vmlinux pathname"), 1144 "file", "vmlinux pathname"),
1145 OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
1146 "Record build-id of all DSOs regardless of hits"),
1141 OPT_END() 1147 OPT_END()
1142}; 1148};
1143 1149
@@ -1255,6 +1261,14 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1255 if (err) 1261 if (err)
1256 goto out_symbol_exit; 1262 goto out_symbol_exit;
1257 1263
1264 /*
1265 * We take all buildids when the file contains
1266 * AUX area tracing data because we do not decode the
1267 * trace because it would take too long.
1268 */
1269 if (rec->opts.full_auxtrace)
1270 rec->buildid_all = true;
1271
1258 if (record_opts__config(&rec->opts)) { 1272 if (record_opts__config(&rec->opts)) {
1259 err = -EINVAL; 1273 err = -EINVAL;
1260 goto out_symbol_exit; 1274 goto out_symbol_exit;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index d5a42ee12529..2bf537f190a0 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -28,6 +28,7 @@
28#include "util/tool.h" 28#include "util/tool.h"
29 29
30#include <subcmd/parse-options.h> 30#include <subcmd/parse-options.h>
31#include <subcmd/exec-cmd.h>
31#include "util/parse-events.h" 32#include "util/parse-events.h"
32 33
33#include "util/thread.h" 34#include "util/thread.h"
@@ -433,7 +434,14 @@ static int report__browse_hists(struct report *rep)
433 int ret; 434 int ret;
434 struct perf_session *session = rep->session; 435 struct perf_session *session = rep->session;
435 struct perf_evlist *evlist = session->evlist; 436 struct perf_evlist *evlist = session->evlist;
436 const char *help = perf_tip(TIPDIR); 437 const char *help = perf_tip(system_path(TIPDIR));
438
439 if (help == NULL) {
440 /* fallback for people who don't install perf ;-) */
441 help = perf_tip(DOCDIR);
442 if (help == NULL)
443 help = "Cannot load tips.txt file, please install perf!";
444 }
437 445
438 switch (use_browser) { 446 switch (use_browser) {
439 case 1: 447 case 1:
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 7f568244662b..038e877081b6 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1588,7 +1588,7 @@ static int add_default_attributes(void)
1588 return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); 1588 return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs);
1589} 1589}
1590 1590
1591static const char * const recort_usage[] = { 1591static const char * const stat_record_usage[] = {
1592 "perf stat record [<options>]", 1592 "perf stat record [<options>]",
1593 NULL, 1593 NULL,
1594}; 1594};
@@ -1611,7 +1611,7 @@ static int __cmd_record(int argc, const char **argv)
1611 struct perf_session *session; 1611 struct perf_session *session;
1612 struct perf_data_file *file = &perf_stat.file; 1612 struct perf_data_file *file = &perf_stat.file;
1613 1613
1614 argc = parse_options(argc, argv, stat_options, record_usage, 1614 argc = parse_options(argc, argv, stat_options, stat_record_usage,
1615 PARSE_OPT_STOP_AT_NON_OPTION); 1615 PARSE_OPT_STOP_AT_NON_OPTION);
1616 1616
1617 if (output_name) 1617 if (output_name)
@@ -1745,7 +1745,7 @@ int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
1745 return set_maps(st); 1745 return set_maps(st);
1746} 1746}
1747 1747
1748static const char * const report_usage[] = { 1748static const char * const stat_report_usage[] = {
1749 "perf stat report [<options>]", 1749 "perf stat report [<options>]",
1750 NULL, 1750 NULL,
1751}; 1751};
@@ -1779,7 +1779,7 @@ static int __cmd_report(int argc, const char **argv)
1779 struct stat st; 1779 struct stat st;
1780 int ret; 1780 int ret;
1781 1781
1782 argc = parse_options(argc, argv, options, report_usage, 0); 1782 argc = parse_options(argc, argv, options, stat_report_usage, 0);
1783 1783
1784 if (!input_name || !strlen(input_name)) { 1784 if (!input_name || !strlen(input_name)) {
1785 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode)) 1785 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 254d06e39bea..e5959c136a19 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -17,7 +17,7 @@ detected_var = $(shell echo "$(1)=$($(1))" >> $(OUTPUT).config-detected)
17 17
18CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS) 18CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS)
19 19
20include $(src-perf)/config/Makefile.arch 20include $(srctree)/tools/scripts/Makefile.arch
21 21
22$(call detected_var,ARCH) 22$(call detected_var,ARCH)
23 23
@@ -493,7 +493,7 @@ else
493 493
494 PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null) 494 PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
495 PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS)) 495 PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
496 PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) 496 PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil
497 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) 497 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
498 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) 498 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
499 499
@@ -692,6 +692,7 @@ template_dir = share/perf-core/templates
692STRACE_GROUPS_DIR = share/perf-core/strace/groups 692STRACE_GROUPS_DIR = share/perf-core/strace/groups
693htmldir = share/doc/perf-doc 693htmldir = share/doc/perf-doc
694tipdir = share/doc/perf-tip 694tipdir = share/doc/perf-tip
695srcdir = $(srctree)/tools/perf
695ifeq ($(prefix),/usr) 696ifeq ($(prefix),/usr)
696sysconfdir = /etc 697sysconfdir = /etc
697ETC_PERFCONFIG = $(sysconfdir)/perfconfig 698ETC_PERFCONFIG = $(sysconfdir)/perfconfig
@@ -722,6 +723,7 @@ tipdir_SQ = $(subst ','\'',$(tipdir))
722prefix_SQ = $(subst ','\'',$(prefix)) 723prefix_SQ = $(subst ','\'',$(prefix))
723sysconfdir_SQ = $(subst ','\'',$(sysconfdir)) 724sysconfdir_SQ = $(subst ','\'',$(sysconfdir))
724libdir_SQ = $(subst ','\'',$(libdir)) 725libdir_SQ = $(subst ','\'',$(libdir))
726srcdir_SQ = $(subst ','\'',$(srcdir))
725 727
726ifneq ($(filter /%,$(firstword $(perfexecdir))),) 728ifneq ($(filter /%,$(firstword $(perfexecdir))),)
727perfexec_instdir = $(perfexecdir) 729perfexec_instdir = $(perfexecdir)
@@ -776,6 +778,7 @@ $(call detected_var,STRACE_GROUPS_DIR_SQ)
776$(call detected_var,prefix_SQ) 778$(call detected_var,prefix_SQ)
777$(call detected_var,perfexecdir_SQ) 779$(call detected_var,perfexecdir_SQ)
778$(call detected_var,tipdir_SQ) 780$(call detected_var,tipdir_SQ)
781$(call detected_var,srcdir_SQ)
779$(call detected_var,LIBDIR) 782$(call detected_var,LIBDIR)
780$(call detected_var,GTK_CFLAGS) 783$(call detected_var,GTK_CFLAGS)
781$(call detected_var,PERL_EMBED_CCOPTS) 784$(call detected_var,PERL_EMBED_CCOPTS)
diff --git a/tools/perf/tests/hists_common.c b/tools/perf/tests/hists_common.c
index bcfd081ee1d2..071a8b5f5232 100644
--- a/tools/perf/tests/hists_common.c
+++ b/tools/perf/tests/hists_common.c
@@ -87,11 +87,6 @@ struct machine *setup_fake_machine(struct machines *machines)
87 return NULL; 87 return NULL;
88 } 88 }
89 89
90 if (machine__create_kernel_maps(machine)) {
91 pr_debug("Cannot create kernel maps\n");
92 return NULL;
93 }
94
95 for (i = 0; i < ARRAY_SIZE(fake_threads); i++) { 90 for (i = 0; i < ARRAY_SIZE(fake_threads); i++) {
96 struct thread *thread; 91 struct thread *thread;
97 92
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index e36089212061..5e6a86e50fb9 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -706,6 +706,7 @@ int test__hists_cumulate(int subtest __maybe_unused)
706 err = parse_events(evlist, "cpu-clock", NULL); 706 err = parse_events(evlist, "cpu-clock", NULL);
707 if (err) 707 if (err)
708 goto out; 708 goto out;
709 err = TEST_FAIL;
709 710
710 machines__init(&machines); 711 machines__init(&machines);
711 712
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index 2a784befd9ce..351a42463444 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -120,6 +120,7 @@ int test__hists_filter(int subtest __maybe_unused)
120 err = parse_events(evlist, "task-clock", NULL); 120 err = parse_events(evlist, "task-clock", NULL);
121 if (err) 121 if (err)
122 goto out; 122 goto out;
123 err = TEST_FAIL;
123 124
124 /* default sort order (comm,dso,sym) will be used */ 125 /* default sort order (comm,dso,sym) will be used */
125 if (setup_sorting(NULL) < 0) 126 if (setup_sorting(NULL) < 0)
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index c764d69ac6ef..64b257d8d557 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -293,6 +293,7 @@ int test__hists_link(int subtest __maybe_unused)
293 if (err) 293 if (err)
294 goto out; 294 goto out;
295 295
296 err = TEST_FAIL;
296 /* default sort order (comm,dso,sym) will be used */ 297 /* default sort order (comm,dso,sym) will be used */
297 if (setup_sorting(NULL) < 0) 298 if (setup_sorting(NULL) < 0)
298 goto out; 299 goto out;
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index ebe6cd485b5d..b231265148d8 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -597,6 +597,7 @@ int test__hists_output(int subtest __maybe_unused)
597 err = parse_events(evlist, "cpu-clock", NULL); 597 err = parse_events(evlist, "cpu-clock", NULL);
598 if (err) 598 if (err)
599 goto out; 599 goto out;
600 err = TEST_FAIL;
600 601
601 machines__init(&machines); 602 machines__init(&machines);
602 603
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index c1fbb8e884c0..df38decc48c3 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -1,3 +1,5 @@
1include ../scripts/Makefile.include
2
1ifndef MK 3ifndef MK
2ifeq ($(MAKECMDGOALS),) 4ifeq ($(MAKECMDGOALS),)
3# no target specified, trigger the whole suite 5# no target specified, trigger the whole suite
@@ -12,7 +14,19 @@ endif
12else 14else
13PERF := . 15PERF := .
14 16
15include config/Makefile.arch 17# As per kernel Makefile, avoid funny character set dependencies
18unexport LC_ALL
19LC_COLLATE=C
20LC_NUMERIC=C
21export LC_COLLATE LC_NUMERIC
22
23ifeq ($(srctree),)
24srctree := $(patsubst %/,%,$(dir $(shell pwd)))
25srctree := $(patsubst %/,%,$(dir $(srctree)))
26#$(info Determined 'srctree' to be $(srctree))
27endif
28
29include $(srctree)/tools/scripts/Makefile.arch
16 30
17# FIXME looks like x86 is the only arch running tests ;-) 31# FIXME looks like x86 is the only arch running tests ;-)
18# we need some IS_(32/64) flag to make this generic 32# we need some IS_(32/64) flag to make this generic
@@ -280,5 +294,5 @@ all: $(run) $(run_O) tarpkg make_kernelsrc make_kernelsrc_tools
280out: $(run_O) 294out: $(run_O)
281 @echo OK 295 @echo OK
282 296
283.PHONY: all $(run) $(run_O) tarpkg clean 297.PHONY: all $(run) $(run_O) tarpkg clean make_kernelsrc make_kernelsrc_tools
284endif # ifndef MK 298endif # ifndef MK
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 901d481e6cea..08c09ad755d2 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -480,7 +480,7 @@ static int hist_browser__run(struct hist_browser *browser, const char *help)
480 480
481 hists__browser_title(browser->hists, hbt, title, sizeof(title)); 481 hists__browser_title(browser->hists, hbt, title, sizeof(title));
482 482
483 if (ui_browser__show(&browser->b, title, help) < 0) 483 if (ui_browser__show(&browser->b, title, "%s", help) < 0)
484 return -1; 484 return -1;
485 485
486 while (1) { 486 while (1) {
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index cd61bb1f3917..85155e91b61b 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -503,7 +503,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
503 if (comm_event == NULL) 503 if (comm_event == NULL)
504 goto out; 504 goto out;
505 505
506 mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size); 506 mmap_event = malloc(sizeof(mmap_event->mmap2) + machine->id_hdr_size);
507 if (mmap_event == NULL) 507 if (mmap_event == NULL)
508 goto out_free_comm; 508 goto out_free_comm;
509 509
@@ -577,7 +577,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
577 if (comm_event == NULL) 577 if (comm_event == NULL)
578 goto out; 578 goto out;
579 579
580 mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size); 580 mmap_event = malloc(sizeof(mmap_event->mmap2) + machine->id_hdr_size);
581 if (mmap_event == NULL) 581 if (mmap_event == NULL)
582 goto out_free_comm; 582 goto out_free_comm;
583 583
diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c
index bdf98f6f27bb..0d3dfcb919b4 100644
--- a/tools/perf/util/strlist.c
+++ b/tools/perf/util/strlist.c
@@ -126,6 +126,11 @@ static int strlist__parse_list_entry(struct strlist *slist, const char *s,
126 err = strlist__load(slist, subst); 126 err = strlist__load(slist, subst);
127 goto out; 127 goto out;
128 } 128 }
129
130 if (slist->file_only) {
131 err = -ENOENT;
132 goto out;
133 }
129 } 134 }
130 135
131 err = strlist__add(slist, s); 136 err = strlist__add(slist, s);
@@ -157,11 +162,13 @@ struct strlist *strlist__new(const char *list, const struct strlist_config *conf
157 162
158 if (slist != NULL) { 163 if (slist != NULL) {
159 bool dupstr = true; 164 bool dupstr = true;
165 bool file_only = false;
160 const char *dirname = NULL; 166 const char *dirname = NULL;
161 167
162 if (config) { 168 if (config) {
163 dupstr = !config->dont_dupstr; 169 dupstr = !config->dont_dupstr;
164 dirname = config->dirname; 170 dirname = config->dirname;
171 file_only = config->file_only;
165 } 172 }
166 173
167 rblist__init(&slist->rblist); 174 rblist__init(&slist->rblist);
@@ -170,6 +177,7 @@ struct strlist *strlist__new(const char *list, const struct strlist_config *conf
170 slist->rblist.node_delete = strlist__node_delete; 177 slist->rblist.node_delete = strlist__node_delete;
171 178
172 slist->dupstr = dupstr; 179 slist->dupstr = dupstr;
180 slist->file_only = file_only;
173 181
174 if (list && strlist__parse_list(slist, list, dirname) != 0) 182 if (list && strlist__parse_list(slist, list, dirname) != 0)
175 goto out_error; 183 goto out_error;
diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h
index 297565aa7535..ca990029e243 100644
--- a/tools/perf/util/strlist.h
+++ b/tools/perf/util/strlist.h
@@ -13,11 +13,18 @@ struct str_node {
13 13
14struct strlist { 14struct strlist {
15 struct rblist rblist; 15 struct rblist rblist;
16 bool dupstr; 16 bool dupstr;
17 bool file_only;
17}; 18};
18 19
20/*
21 * @file_only: When dirname is present, only consider entries as filenames,
22 * that should not be added to the list if dirname/entry is not
23 * found
24 */
19struct strlist_config { 25struct strlist_config {
20 bool dont_dupstr; 26 bool dont_dupstr;
27 bool file_only;
21 const char *dirname; 28 const char *dirname;
22}; 29};
23 30
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 88b8f8d21f58..ead9509835d2 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -17,7 +17,6 @@
17#include <unistd.h> 17#include <unistd.h>
18#include "callchain.h" 18#include "callchain.h"
19#include "strlist.h" 19#include "strlist.h"
20#include <subcmd/exec-cmd.h>
21 20
22struct callchain_param callchain_param = { 21struct callchain_param callchain_param = {
23 .mode = CHAIN_GRAPH_ABS, 22 .mode = CHAIN_GRAPH_ABS,
@@ -672,14 +671,16 @@ const char *perf_tip(const char *dirpath)
672 struct str_node *node; 671 struct str_node *node;
673 char *tip = NULL; 672 char *tip = NULL;
674 struct strlist_config conf = { 673 struct strlist_config conf = {
675 .dirname = system_path(dirpath) , 674 .dirname = dirpath,
675 .file_only = true,
676 }; 676 };
677 677
678 tips = strlist__new("tips.txt", &conf); 678 tips = strlist__new("tips.txt", &conf);
679 if (tips == NULL || strlist__nr_entries(tips) == 1) { 679 if (tips == NULL)
680 tip = (char *)"Cannot find tips.txt file"; 680 return errno == ENOENT ? NULL : "Tip: get more memory! ;-p";
681
682 if (strlist__nr_entries(tips) == 0)
681 goto out; 683 goto out;
682 }
683 684
684 node = strlist__entry(tips, random() % strlist__nr_entries(tips)); 685 node = strlist__entry(tips, random() % strlist__nr_entries(tips));
685 if (asprintf(&tip, "Tip: %s", node->s) < 0) 686 if (asprintf(&tip, "Tip: %s", node->s) < 0)
diff --git a/tools/perf/config/Makefile.arch b/tools/scripts/Makefile.arch
index e11fbd6fae78..e11fbd6fae78 100644
--- a/tools/perf/config/Makefile.arch
+++ b/tools/scripts/Makefile.arch
diff --git a/tools/spi/.gitignore b/tools/spi/.gitignore
new file mode 100644
index 000000000000..4280576397e8
--- /dev/null
+++ b/tools/spi/.gitignore
@@ -0,0 +1,2 @@
1spidev_fdx
2spidev_test
diff --git a/tools/spi/Makefile b/tools/spi/Makefile
new file mode 100644
index 000000000000..cd0db62e4d9d
--- /dev/null
+++ b/tools/spi/Makefile
@@ -0,0 +1,4 @@
1all: spidev_test spidev_fdx
2
3clean:
4 $(RM) spidev_test spidev_fdx
diff --git a/tools/spi/spidev_fdx.c b/tools/spi/spidev_fdx.c
new file mode 100644
index 000000000000..0ea3e51292fc
--- /dev/null
+++ b/tools/spi/spidev_fdx.c
@@ -0,0 +1,158 @@
1#include <stdio.h>
2#include <unistd.h>
3#include <stdlib.h>
4#include <fcntl.h>
5#include <string.h>
6
7#include <sys/ioctl.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10
11#include <linux/types.h>
12#include <linux/spi/spidev.h>
13
14
15static int verbose;
16
17static void do_read(int fd, int len)
18{
19 unsigned char buf[32], *bp;
20 int status;
21
22 /* read at least 2 bytes, no more than 32 */
23 if (len < 2)
24 len = 2;
25 else if (len > sizeof(buf))
26 len = sizeof(buf);
27 memset(buf, 0, sizeof buf);
28
29 status = read(fd, buf, len);
30 if (status < 0) {
31 perror("read");
32 return;
33 }
34 if (status != len) {
35 fprintf(stderr, "short read\n");
36 return;
37 }
38
39 printf("read(%2d, %2d): %02x %02x,", len, status,
40 buf[0], buf[1]);
41 status -= 2;
42 bp = buf + 2;
43 while (status-- > 0)
44 printf(" %02x", *bp++);
45 printf("\n");
46}
47
48static void do_msg(int fd, int len)
49{
50 struct spi_ioc_transfer xfer[2];
51 unsigned char buf[32], *bp;
52 int status;
53
54 memset(xfer, 0, sizeof xfer);
55 memset(buf, 0, sizeof buf);
56
57 if (len > sizeof buf)
58 len = sizeof buf;
59
60 buf[0] = 0xaa;
61 xfer[0].tx_buf = (unsigned long)buf;
62 xfer[0].len = 1;
63
64 xfer[1].rx_buf = (unsigned long) buf;
65 xfer[1].len = len;
66
67 status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer);
68 if (status < 0) {
69 perror("SPI_IOC_MESSAGE");
70 return;
71 }
72
73 printf("response(%2d, %2d): ", len, status);
74 for (bp = buf; len; len--)
75 printf(" %02x", *bp++);
76 printf("\n");
77}
78
79static void dumpstat(const char *name, int fd)
80{
81 __u8 lsb, bits;
82 __u32 mode, speed;
83
84 if (ioctl(fd, SPI_IOC_RD_MODE32, &mode) < 0) {
85 perror("SPI rd_mode");
86 return;
87 }
88 if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) {
89 perror("SPI rd_lsb_fist");
90 return;
91 }
92 if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) {
93 perror("SPI bits_per_word");
94 return;
95 }
96 if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) {
97 perror("SPI max_speed_hz");
98 return;
99 }
100
101 printf("%s: spi mode 0x%x, %d bits %sper word, %d Hz max\n",
102 name, mode, bits, lsb ? "(lsb first) " : "", speed);
103}
104
105int main(int argc, char **argv)
106{
107 int c;
108 int readcount = 0;
109 int msglen = 0;
110 int fd;
111 const char *name;
112
113 while ((c = getopt(argc, argv, "hm:r:v")) != EOF) {
114 switch (c) {
115 case 'm':
116 msglen = atoi(optarg);
117 if (msglen < 0)
118 goto usage;
119 continue;
120 case 'r':
121 readcount = atoi(optarg);
122 if (readcount < 0)
123 goto usage;
124 continue;
125 case 'v':
126 verbose++;
127 continue;
128 case 'h':
129 case '?':
130usage:
131 fprintf(stderr,
132 "usage: %s [-h] [-m N] [-r N] /dev/spidevB.D\n",
133 argv[0]);
134 return 1;
135 }
136 }
137
138 if ((optind + 1) != argc)
139 goto usage;
140 name = argv[optind];
141
142 fd = open(name, O_RDWR);
143 if (fd < 0) {
144 perror("open");
145 return 1;
146 }
147
148 dumpstat(name, fd);
149
150 if (msglen)
151 do_msg(fd, msglen);
152
153 if (readcount)
154 do_read(fd, readcount);
155
156 close(fd);
157 return 0;
158}
diff --git a/tools/spi/spidev_test.c b/tools/spi/spidev_test.c
new file mode 100644
index 000000000000..8a73d8185316
--- /dev/null
+++ b/tools/spi/spidev_test.c
@@ -0,0 +1,399 @@
1/*
2 * SPI testing utility (using spidev driver)
3 *
4 * Copyright (c) 2007 MontaVista Software, Inc.
5 * Copyright (c) 2007 Anton Vorontsov <avorontsov@ru.mvista.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License.
10 *
11 * Cross-compile with cross-gcc -I/path/to/cross-kernel/include
12 */
13
14#include <stdint.h>
15#include <unistd.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <getopt.h>
20#include <fcntl.h>
21#include <sys/ioctl.h>
22#include <sys/stat.h>
23#include <linux/types.h>
24#include <linux/spi/spidev.h>
25
26#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
27
28static void pabort(const char *s)
29{
30 perror(s);
31 abort();
32}
33
34static const char *device = "/dev/spidev1.1";
35static uint32_t mode;
36static uint8_t bits = 8;
37static char *input_file;
38static char *output_file;
39static uint32_t speed = 500000;
40static uint16_t delay;
41static int verbose;
42
43uint8_t default_tx[] = {
44 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
45 0x40, 0x00, 0x00, 0x00, 0x00, 0x95,
46 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
47 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
48 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
49 0xF0, 0x0D,
50};
51
52uint8_t default_rx[ARRAY_SIZE(default_tx)] = {0, };
53char *input_tx;
54
55static void hex_dump(const void *src, size_t length, size_t line_size,
56 char *prefix)
57{
58 int i = 0;
59 const unsigned char *address = src;
60 const unsigned char *line = address;
61 unsigned char c;
62
63 printf("%s | ", prefix);
64 while (length-- > 0) {
65 printf("%02X ", *address++);
66 if (!(++i % line_size) || (length == 0 && i % line_size)) {
67 if (length == 0) {
68 while (i++ % line_size)
69 printf("__ ");
70 }
71 printf(" | "); /* right close */
72 while (line < address) {
73 c = *line++;
74 printf("%c", (c < 33 || c == 255) ? 0x2E : c);
75 }
76 printf("\n");
77 if (length > 0)
78 printf("%s | ", prefix);
79 }
80 }
81}
82
83/*
84 * Unescape - process hexadecimal escape character
85 * converts shell input "\x23" -> 0x23
86 */
87static int unescape(char *_dst, char *_src, size_t len)
88{
89 int ret = 0;
90 int match;
91 char *src = _src;
92 char *dst = _dst;
93 unsigned int ch;
94
95 while (*src) {
96 if (*src == '\\' && *(src+1) == 'x') {
97 match = sscanf(src + 2, "%2x", &ch);
98 if (!match)
99 pabort("malformed input string");
100
101 src += 4;
102 *dst++ = (unsigned char)ch;
103 } else {
104 *dst++ = *src++;
105 }
106 ret++;
107 }
108 return ret;
109}
110
111static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
112{
113 int ret;
114 int out_fd;
115 struct spi_ioc_transfer tr = {
116 .tx_buf = (unsigned long)tx,
117 .rx_buf = (unsigned long)rx,
118 .len = len,
119 .delay_usecs = delay,
120 .speed_hz = speed,
121 .bits_per_word = bits,
122 };
123
124 if (mode & SPI_TX_QUAD)
125 tr.tx_nbits = 4;
126 else if (mode & SPI_TX_DUAL)
127 tr.tx_nbits = 2;
128 if (mode & SPI_RX_QUAD)
129 tr.rx_nbits = 4;
130 else if (mode & SPI_RX_DUAL)
131 tr.rx_nbits = 2;
132 if (!(mode & SPI_LOOP)) {
133 if (mode & (SPI_TX_QUAD | SPI_TX_DUAL))
134 tr.rx_buf = 0;
135 else if (mode & (SPI_RX_QUAD | SPI_RX_DUAL))
136 tr.tx_buf = 0;
137 }
138
139 ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
140 if (ret < 1)
141 pabort("can't send spi message");
142
143 if (verbose)
144 hex_dump(tx, len, 32, "TX");
145
146 if (output_file) {
147 out_fd = open(output_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
148 if (out_fd < 0)
149 pabort("could not open output file");
150
151 ret = write(out_fd, rx, len);
152 if (ret != len)
153 pabort("not all bytes written to output file");
154
155 close(out_fd);
156 }
157
158 if (verbose || !output_file)
159 hex_dump(rx, len, 32, "RX");
160}
161
162static void print_usage(const char *prog)
163{
164 printf("Usage: %s [-DsbdlHOLC3]\n", prog);
165 puts(" -D --device device to use (default /dev/spidev1.1)\n"
166 " -s --speed max speed (Hz)\n"
167 " -d --delay delay (usec)\n"
168 " -b --bpw bits per word\n"
169 " -i --input input data from a file (e.g. \"test.bin\")\n"
170 " -o --output output data to a file (e.g. \"results.bin\")\n"
171 " -l --loop loopback\n"
172 " -H --cpha clock phase\n"
173 " -O --cpol clock polarity\n"
174 " -L --lsb least significant bit first\n"
175 " -C --cs-high chip select active high\n"
176 " -3 --3wire SI/SO signals shared\n"
177 " -v --verbose Verbose (show tx buffer)\n"
178 " -p Send data (e.g. \"1234\\xde\\xad\")\n"
179 " -N --no-cs no chip select\n"
180 " -R --ready slave pulls low to pause\n"
181 " -2 --dual dual transfer\n"
182 " -4 --quad quad transfer\n");
183 exit(1);
184}
185
186static void parse_opts(int argc, char *argv[])
187{
188 while (1) {
189 static const struct option lopts[] = {
190 { "device", 1, 0, 'D' },
191 { "speed", 1, 0, 's' },
192 { "delay", 1, 0, 'd' },
193 { "bpw", 1, 0, 'b' },
194 { "input", 1, 0, 'i' },
195 { "output", 1, 0, 'o' },
196 { "loop", 0, 0, 'l' },
197 { "cpha", 0, 0, 'H' },
198 { "cpol", 0, 0, 'O' },
199 { "lsb", 0, 0, 'L' },
200 { "cs-high", 0, 0, 'C' },
201 { "3wire", 0, 0, '3' },
202 { "no-cs", 0, 0, 'N' },
203 { "ready", 0, 0, 'R' },
204 { "dual", 0, 0, '2' },
205 { "verbose", 0, 0, 'v' },
206 { "quad", 0, 0, '4' },
207 { NULL, 0, 0, 0 },
208 };
209 int c;
210
211 c = getopt_long(argc, argv, "D:s:d:b:i:o:lHOLC3NR24p:v",
212 lopts, NULL);
213
214 if (c == -1)
215 break;
216
217 switch (c) {
218 case 'D':
219 device = optarg;
220 break;
221 case 's':
222 speed = atoi(optarg);
223 break;
224 case 'd':
225 delay = atoi(optarg);
226 break;
227 case 'b':
228 bits = atoi(optarg);
229 break;
230 case 'i':
231 input_file = optarg;
232 break;
233 case 'o':
234 output_file = optarg;
235 break;
236 case 'l':
237 mode |= SPI_LOOP;
238 break;
239 case 'H':
240 mode |= SPI_CPHA;
241 break;
242 case 'O':
243 mode |= SPI_CPOL;
244 break;
245 case 'L':
246 mode |= SPI_LSB_FIRST;
247 break;
248 case 'C':
249 mode |= SPI_CS_HIGH;
250 break;
251 case '3':
252 mode |= SPI_3WIRE;
253 break;
254 case 'N':
255 mode |= SPI_NO_CS;
256 break;
257 case 'v':
258 verbose = 1;
259 break;
260 case 'R':
261 mode |= SPI_READY;
262 break;
263 case 'p':
264 input_tx = optarg;
265 break;
266 case '2':
267 mode |= SPI_TX_DUAL;
268 break;
269 case '4':
270 mode |= SPI_TX_QUAD;
271 break;
272 default:
273 print_usage(argv[0]);
274 break;
275 }
276 }
277 if (mode & SPI_LOOP) {
278 if (mode & SPI_TX_DUAL)
279 mode |= SPI_RX_DUAL;
280 if (mode & SPI_TX_QUAD)
281 mode |= SPI_RX_QUAD;
282 }
283}
284
285static void transfer_escaped_string(int fd, char *str)
286{
287 size_t size = strlen(str + 1);
288 uint8_t *tx;
289 uint8_t *rx;
290
291 tx = malloc(size);
292 if (!tx)
293 pabort("can't allocate tx buffer");
294
295 rx = malloc(size);
296 if (!rx)
297 pabort("can't allocate rx buffer");
298
299 size = unescape((char *)tx, str, size);
300 transfer(fd, tx, rx, size);
301 free(rx);
302 free(tx);
303}
304
305static void transfer_file(int fd, char *filename)
306{
307 ssize_t bytes;
308 struct stat sb;
309 int tx_fd;
310 uint8_t *tx;
311 uint8_t *rx;
312
313 if (stat(filename, &sb) == -1)
314 pabort("can't stat input file");
315
316 tx_fd = open(filename, O_RDONLY);
317 if (fd < 0)
318 pabort("can't open input file");
319
320 tx = malloc(sb.st_size);
321 if (!tx)
322 pabort("can't allocate tx buffer");
323
324 rx = malloc(sb.st_size);
325 if (!rx)
326 pabort("can't allocate rx buffer");
327
328 bytes = read(tx_fd, tx, sb.st_size);
329 if (bytes != sb.st_size)
330 pabort("failed to read input file");
331
332 transfer(fd, tx, rx, sb.st_size);
333 free(rx);
334 free(tx);
335 close(tx_fd);
336}
337
338int main(int argc, char *argv[])
339{
340 int ret = 0;
341 int fd;
342
343 parse_opts(argc, argv);
344
345 fd = open(device, O_RDWR);
346 if (fd < 0)
347 pabort("can't open device");
348
349 /*
350 * spi mode
351 */
352 ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);
353 if (ret == -1)
354 pabort("can't set spi mode");
355
356 ret = ioctl(fd, SPI_IOC_RD_MODE32, &mode);
357 if (ret == -1)
358 pabort("can't get spi mode");
359
360 /*
361 * bits per word
362 */
363 ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
364 if (ret == -1)
365 pabort("can't set bits per word");
366
367 ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
368 if (ret == -1)
369 pabort("can't get bits per word");
370
371 /*
372 * max speed hz
373 */
374 ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
375 if (ret == -1)
376 pabort("can't set max speed hz");
377
378 ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
379 if (ret == -1)
380 pabort("can't get max speed hz");
381
382 printf("spi mode: 0x%x\n", mode);
383 printf("bits per word: %d\n", bits);
384 printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
385
386 if (input_tx && input_file)
387 pabort("only one of -p and --input may be selected");
388
389 if (input_tx)
390 transfer_escaped_string(fd, input_tx);
391 else if (input_file)
392 transfer_file(fd, input_file);
393 else
394 transfer(fd, default_tx, default_rx, sizeof(default_tx));
395
396 close(fd);
397
398 return ret;
399}
diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild
index 38b00ecb2ed5..a34bfd0c8928 100644
--- a/tools/testing/nvdimm/Kbuild
+++ b/tools/testing/nvdimm/Kbuild
@@ -9,6 +9,8 @@ ldflags-y += --wrap=memunmap
9ldflags-y += --wrap=__devm_request_region 9ldflags-y += --wrap=__devm_request_region
10ldflags-y += --wrap=__request_region 10ldflags-y += --wrap=__request_region
11ldflags-y += --wrap=__release_region 11ldflags-y += --wrap=__release_region
12ldflags-y += --wrap=devm_memremap_pages
13ldflags-y += --wrap=phys_to_pfn_t
12 14
13DRIVERS := ../../../drivers 15DRIVERS := ../../../drivers
14NVDIMM_SRC := $(DRIVERS)/nvdimm 16NVDIMM_SRC := $(DRIVERS)/nvdimm
diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c
index b7251314bbc0..7ec7df9e7fc7 100644
--- a/tools/testing/nvdimm/test/iomap.c
+++ b/tools/testing/nvdimm/test/iomap.c
@@ -16,6 +16,7 @@
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/types.h> 17#include <linux/types.h>
18#include <linux/io.h> 18#include <linux/io.h>
19#include <linux/mm.h>
19#include "nfit_test.h" 20#include "nfit_test.h"
20 21
21static LIST_HEAD(iomap_head); 22static LIST_HEAD(iomap_head);
@@ -41,7 +42,7 @@ void nfit_test_teardown(void)
41} 42}
42EXPORT_SYMBOL(nfit_test_teardown); 43EXPORT_SYMBOL(nfit_test_teardown);
43 44
44static struct nfit_test_resource *get_nfit_res(resource_size_t resource) 45static struct nfit_test_resource *__get_nfit_res(resource_size_t resource)
45{ 46{
46 struct iomap_ops *ops; 47 struct iomap_ops *ops;
47 48
@@ -51,14 +52,22 @@ static struct nfit_test_resource *get_nfit_res(resource_size_t resource)
51 return NULL; 52 return NULL;
52} 53}
53 54
54void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size, 55static struct nfit_test_resource *get_nfit_res(resource_size_t resource)
55 void __iomem *(*fallback_fn)(resource_size_t, unsigned long))
56{ 56{
57 struct nfit_test_resource *nfit_res; 57 struct nfit_test_resource *res;
58 58
59 rcu_read_lock(); 59 rcu_read_lock();
60 nfit_res = get_nfit_res(offset); 60 res = __get_nfit_res(resource);
61 rcu_read_unlock(); 61 rcu_read_unlock();
62
63 return res;
64}
65
66void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size,
67 void __iomem *(*fallback_fn)(resource_size_t, unsigned long))
68{
69 struct nfit_test_resource *nfit_res = get_nfit_res(offset);
70
62 if (nfit_res) 71 if (nfit_res)
63 return (void __iomem *) nfit_res->buf + offset 72 return (void __iomem *) nfit_res->buf + offset
64 - nfit_res->res->start; 73 - nfit_res->res->start;
@@ -68,11 +77,8 @@ void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size,
68void __iomem *__wrap_devm_ioremap_nocache(struct device *dev, 77void __iomem *__wrap_devm_ioremap_nocache(struct device *dev,
69 resource_size_t offset, unsigned long size) 78 resource_size_t offset, unsigned long size)
70{ 79{
71 struct nfit_test_resource *nfit_res; 80 struct nfit_test_resource *nfit_res = get_nfit_res(offset);
72 81
73 rcu_read_lock();
74 nfit_res = get_nfit_res(offset);
75 rcu_read_unlock();
76 if (nfit_res) 82 if (nfit_res)
77 return (void __iomem *) nfit_res->buf + offset 83 return (void __iomem *) nfit_res->buf + offset
78 - nfit_res->res->start; 84 - nfit_res->res->start;
@@ -83,25 +89,58 @@ EXPORT_SYMBOL(__wrap_devm_ioremap_nocache);
83void *__wrap_devm_memremap(struct device *dev, resource_size_t offset, 89void *__wrap_devm_memremap(struct device *dev, resource_size_t offset,
84 size_t size, unsigned long flags) 90 size_t size, unsigned long flags)
85{ 91{
86 struct nfit_test_resource *nfit_res; 92 struct nfit_test_resource *nfit_res = get_nfit_res(offset);
87 93
88 rcu_read_lock();
89 nfit_res = get_nfit_res(offset);
90 rcu_read_unlock();
91 if (nfit_res) 94 if (nfit_res)
92 return nfit_res->buf + offset - nfit_res->res->start; 95 return nfit_res->buf + offset - nfit_res->res->start;
93 return devm_memremap(dev, offset, size, flags); 96 return devm_memremap(dev, offset, size, flags);
94} 97}
95EXPORT_SYMBOL(__wrap_devm_memremap); 98EXPORT_SYMBOL(__wrap_devm_memremap);
96 99
100#ifdef __HAVE_ARCH_PTE_DEVMAP
101#include <linux/memremap.h>
102#include <linux/pfn_t.h>
103
104void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res,
105 struct percpu_ref *ref, struct vmem_altmap *altmap)
106{
107 resource_size_t offset = res->start;
108 struct nfit_test_resource *nfit_res = get_nfit_res(offset);
109
110 if (nfit_res)
111 return nfit_res->buf + offset - nfit_res->res->start;
112 return devm_memremap_pages(dev, res, ref, altmap);
113}
114EXPORT_SYMBOL(__wrap_devm_memremap_pages);
115
116pfn_t __wrap_phys_to_pfn_t(dma_addr_t addr, unsigned long flags)
117{
118 struct nfit_test_resource *nfit_res = get_nfit_res(addr);
119
120 if (nfit_res)
121 flags &= ~PFN_MAP;
122 return phys_to_pfn_t(addr, flags);
123}
124EXPORT_SYMBOL(__wrap_phys_to_pfn_t);
125#else
126/* to be removed post 4.5-rc1 */
127void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res)
128{
129 resource_size_t offset = res->start;
130 struct nfit_test_resource *nfit_res = get_nfit_res(offset);
131
132 if (nfit_res)
133 return nfit_res->buf + offset - nfit_res->res->start;
134 return devm_memremap_pages(dev, res);
135}
136EXPORT_SYMBOL(__wrap_devm_memremap_pages);
137#endif
138
97void *__wrap_memremap(resource_size_t offset, size_t size, 139void *__wrap_memremap(resource_size_t offset, size_t size,
98 unsigned long flags) 140 unsigned long flags)
99{ 141{
100 struct nfit_test_resource *nfit_res; 142 struct nfit_test_resource *nfit_res = get_nfit_res(offset);
101 143
102 rcu_read_lock();
103 nfit_res = get_nfit_res(offset);
104 rcu_read_unlock();
105 if (nfit_res) 144 if (nfit_res)
106 return nfit_res->buf + offset - nfit_res->res->start; 145 return nfit_res->buf + offset - nfit_res->res->start;
107 return memremap(offset, size, flags); 146 return memremap(offset, size, flags);
@@ -110,11 +149,8 @@ EXPORT_SYMBOL(__wrap_memremap);
110 149
111void __wrap_devm_memunmap(struct device *dev, void *addr) 150void __wrap_devm_memunmap(struct device *dev, void *addr)
112{ 151{
113 struct nfit_test_resource *nfit_res; 152 struct nfit_test_resource *nfit_res = get_nfit_res((long) addr);
114 153
115 rcu_read_lock();
116 nfit_res = get_nfit_res((unsigned long) addr);
117 rcu_read_unlock();
118 if (nfit_res) 154 if (nfit_res)
119 return; 155 return;
120 return devm_memunmap(dev, addr); 156 return devm_memunmap(dev, addr);
@@ -135,11 +171,7 @@ EXPORT_SYMBOL(__wrap_ioremap_wc);
135 171
136void __wrap_iounmap(volatile void __iomem *addr) 172void __wrap_iounmap(volatile void __iomem *addr)
137{ 173{
138 struct nfit_test_resource *nfit_res; 174 struct nfit_test_resource *nfit_res = get_nfit_res((long) addr);
139
140 rcu_read_lock();
141 nfit_res = get_nfit_res((unsigned long) addr);
142 rcu_read_unlock();
143 if (nfit_res) 175 if (nfit_res)
144 return; 176 return;
145 return iounmap(addr); 177 return iounmap(addr);
@@ -148,11 +180,8 @@ EXPORT_SYMBOL(__wrap_iounmap);
148 180
149void __wrap_memunmap(void *addr) 181void __wrap_memunmap(void *addr)
150{ 182{
151 struct nfit_test_resource *nfit_res; 183 struct nfit_test_resource *nfit_res = get_nfit_res((long) addr);
152 184
153 rcu_read_lock();
154 nfit_res = get_nfit_res((unsigned long) addr);
155 rcu_read_unlock();
156 if (nfit_res) 185 if (nfit_res)
157 return; 186 return;
158 return memunmap(addr); 187 return memunmap(addr);
@@ -166,9 +195,7 @@ static struct resource *nfit_test_request_region(struct device *dev,
166 struct nfit_test_resource *nfit_res; 195 struct nfit_test_resource *nfit_res;
167 196
168 if (parent == &iomem_resource) { 197 if (parent == &iomem_resource) {
169 rcu_read_lock();
170 nfit_res = get_nfit_res(start); 198 nfit_res = get_nfit_res(start);
171 rcu_read_unlock();
172 if (nfit_res) { 199 if (nfit_res) {
173 struct resource *res = nfit_res->res + 1; 200 struct resource *res = nfit_res->res + 1;
174 201
@@ -218,9 +245,7 @@ void __wrap___release_region(struct resource *parent, resource_size_t start,
218 struct nfit_test_resource *nfit_res; 245 struct nfit_test_resource *nfit_res;
219 246
220 if (parent == &iomem_resource) { 247 if (parent == &iomem_resource) {
221 rcu_read_lock();
222 nfit_res = get_nfit_res(start); 248 nfit_res = get_nfit_res(start);
223 rcu_read_unlock();
224 if (nfit_res) { 249 if (nfit_res) {
225 struct resource *res = nfit_res->res + 1; 250 struct resource *res = nfit_res->res + 1;
226 251
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 51cf8256c6cd..90bd2ea41032 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -248,6 +248,8 @@ static int nfit_test_cmd_ars_status(struct nd_cmd_ars_status *nd_cmd,
248 248
249 nd_cmd->out_length = 256; 249 nd_cmd->out_length = 256;
250 nd_cmd->num_records = 0; 250 nd_cmd->num_records = 0;
251 nd_cmd->address = 0;
252 nd_cmd->length = -1ULL;
251 nd_cmd->status = 0; 253 nd_cmd->status = 0;
252 254
253 return 0; 255 return 0;
@@ -1088,6 +1090,8 @@ static void nfit_test1_setup(struct nfit_test *t)
1088 struct acpi_nfit_memory_map *memdev; 1090 struct acpi_nfit_memory_map *memdev;
1089 struct acpi_nfit_control_region *dcr; 1091 struct acpi_nfit_control_region *dcr;
1090 struct acpi_nfit_system_address *spa; 1092 struct acpi_nfit_system_address *spa;
1093 struct nvdimm_bus_descriptor *nd_desc;
1094 struct acpi_nfit_desc *acpi_desc;
1091 1095
1092 offset = 0; 1096 offset = 0;
1093 /* spa0 (flat range with no bdw aliasing) */ 1097 /* spa0 (flat range with no bdw aliasing) */
@@ -1135,6 +1139,13 @@ static void nfit_test1_setup(struct nfit_test *t)
1135 dcr->command_size = 0; 1139 dcr->command_size = 0;
1136 dcr->status_offset = 0; 1140 dcr->status_offset = 0;
1137 dcr->status_size = 0; 1141 dcr->status_size = 0;
1142
1143 acpi_desc = &t->acpi_desc;
1144 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en);
1145 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en);
1146 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_dsm_force_en);
1147 nd_desc = &acpi_desc->nd_desc;
1148 nd_desc->ndctl = nfit_test_ctl;
1138} 1149}
1139 1150
1140static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa, 1151static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index c8edff6803d1..b04afc3295df 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -1,10 +1,12 @@
1TARGETS = breakpoints 1TARGETS = breakpoints
2TARGETS += capabilities
2TARGETS += cpu-hotplug 3TARGETS += cpu-hotplug
3TARGETS += efivarfs 4TARGETS += efivarfs
4TARGETS += exec 5TARGETS += exec
5TARGETS += firmware 6TARGETS += firmware
6TARGETS += ftrace 7TARGETS += ftrace
7TARGETS += futex 8TARGETS += futex
9TARGETS += ipc
8TARGETS += kcmp 10TARGETS += kcmp
9TARGETS += lib 11TARGETS += lib
10TARGETS += membarrier 12TARGETS += membarrier
diff --git a/tools/testing/selftests/breakpoints/.gitignore b/tools/testing/selftests/breakpoints/.gitignore
new file mode 100644
index 000000000000..9b3193d06608
--- /dev/null
+++ b/tools/testing/selftests/breakpoints/.gitignore
@@ -0,0 +1 @@
breakpoint_test
diff --git a/tools/testing/selftests/capabilities/Makefile b/tools/testing/selftests/capabilities/Makefile
index 8c8f0c1f0889..008602aed920 100644
--- a/tools/testing/selftests/capabilities/Makefile
+++ b/tools/testing/selftests/capabilities/Makefile
@@ -1,18 +1,15 @@
1all: 1TEST_FILES := validate_cap
2
3include ../lib.mk
4
5.PHONY: all clean
6
7TARGETS := validate_cap test_execve
8TEST_PROGS := test_execve 2TEST_PROGS := test_execve
9 3
10CFLAGS := -O2 -g -std=gnu99 -Wall -lcap-ng 4BINARIES := $(TEST_FILES) $(TEST_PROGS)
11 5
12all: $(TARGETS) 6CFLAGS += -O2 -g -std=gnu99 -Wall
7LDLIBS += -lcap-ng -lrt -ldl
8
9all: $(BINARIES)
13 10
14clean: 11clean:
15 $(RM) $(TARGETS) 12 $(RM) $(BINARIES)
13
14include ../lib.mk
16 15
17$(TARGETS): %: %.c
18 $(CC) -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
diff --git a/tools/testing/selftests/firmware/fw_filesystem.sh b/tools/testing/selftests/firmware/fw_filesystem.sh
index c4366dc74e01..5c495ad7958a 100755
--- a/tools/testing/selftests/firmware/fw_filesystem.sh
+++ b/tools/testing/selftests/firmware/fw_filesystem.sh
@@ -48,8 +48,21 @@ echo "ABCD0123" >"$FW"
48 48
49NAME=$(basename "$FW") 49NAME=$(basename "$FW")
50 50
51if printf '\000' >"$DIR"/trigger_request; then
52 echo "$0: empty filename should not succeed" >&2
53 exit 1
54fi
55
56if printf '\000' >"$DIR"/trigger_async_request; then
57 echo "$0: empty filename should not succeed (async)" >&2
58 exit 1
59fi
60
51# Request a firmware that doesn't exist, it should fail. 61# Request a firmware that doesn't exist, it should fail.
52echo -n "nope-$NAME" >"$DIR"/trigger_request 62if echo -n "nope-$NAME" >"$DIR"/trigger_request; then
63 echo "$0: firmware shouldn't have loaded" >&2
64 exit 1
65fi
53if diff -q "$FW" /dev/test_firmware >/dev/null ; then 66if diff -q "$FW" /dev/test_firmware >/dev/null ; then
54 echo "$0: firmware was not expected to match" >&2 67 echo "$0: firmware was not expected to match" >&2
55 exit 1 68 exit 1
@@ -74,4 +87,18 @@ else
74 echo "$0: filesystem loading works" 87 echo "$0: filesystem loading works"
75fi 88fi
76 89
90# Try the asynchronous version too
91if ! echo -n "$NAME" >"$DIR"/trigger_async_request ; then
92 echo "$0: could not trigger async request" >&2
93 exit 1
94fi
95
96# Verify the contents are what we expect.
97if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
98 echo "$0: firmware was not loaded (async)" >&2
99 exit 1
100else
101 echo "$0: async filesystem loading works"
102fi
103
77exit 0 104exit 0
diff --git a/tools/testing/selftests/intel_pstate/Makefile b/tools/testing/selftests/intel_pstate/Makefile
new file mode 100644
index 000000000000..f5f1a28715ff
--- /dev/null
+++ b/tools/testing/selftests/intel_pstate/Makefile
@@ -0,0 +1,15 @@
1CC := $(CROSS_COMPILE)gcc
2CFLAGS := $(CFLAGS) -Wall -D_GNU_SOURCE
3LDFLAGS := $(LDFLAGS) -lm
4
5TARGETS := msr aperf
6
7TEST_PROGS := $(TARGETS) run.sh
8
9.PHONY: all clean
10all: $(TARGETS)
11
12$(TARGETS): $(HEADERS)
13
14clean:
15 rm -f $(TARGETS)
diff --git a/tools/testing/selftests/intel_pstate/aperf.c b/tools/testing/selftests/intel_pstate/aperf.c
new file mode 100644
index 000000000000..6046e183f4ad
--- /dev/null
+++ b/tools/testing/selftests/intel_pstate/aperf.c
@@ -0,0 +1,80 @@
1#include <math.h>
2#include <unistd.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <fcntl.h>
8#include <sys/timeb.h>
9#include <sched.h>
10#include <errno.h>
11
12void usage(char *name) {
13 printf ("Usage: %s cpunum\n", name);
14}
15
16int main(int argc, char **argv) {
17 int i, cpu, fd;
18 char msr_file_name[64];
19 long long tsc, old_tsc, new_tsc;
20 long long aperf, old_aperf, new_aperf;
21 long long mperf, old_mperf, new_mperf;
22 struct timeb before, after;
23 long long int start, finish, total;
24 cpu_set_t cpuset;
25
26 if (argc != 2) {
27 usage(argv[0]);
28 return 1;
29 }
30
31 errno = 0;
32 cpu = strtol(argv[1], (char **) NULL, 10);
33
34 if (errno) {
35 usage(argv[0]);
36 return 1;
37 }
38
39 sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu);
40 fd = open(msr_file_name, O_RDONLY);
41
42 if (fd == -1) {
43 perror("Failed to open");
44 return 1;
45 }
46
47 CPU_ZERO(&cpuset);
48 CPU_SET(cpu, &cpuset);
49
50 if (sched_setaffinity(0, sizeof(cpu_set_t), &cpuset)) {
51 perror("Failed to set cpu affinity");
52 return 1;
53 }
54
55 ftime(&before);
56 pread(fd, &old_tsc, sizeof(old_tsc), 0x10);
57 pread(fd, &old_aperf, sizeof(old_mperf), 0xe7);
58 pread(fd, &old_mperf, sizeof(old_aperf), 0xe8);
59
60 for (i=0; i<0x8fffffff; i++) {
61 sqrt(i);
62 }
63
64 ftime(&after);
65 pread(fd, &new_tsc, sizeof(new_tsc), 0x10);
66 pread(fd, &new_aperf, sizeof(new_mperf), 0xe7);
67 pread(fd, &new_mperf, sizeof(new_aperf), 0xe8);
68
69 tsc = new_tsc-old_tsc;
70 aperf = new_aperf-old_aperf;
71 mperf = new_mperf-old_mperf;
72
73 start = before.time*1000 + before.millitm;
74 finish = after.time*1000 + after.millitm;
75 total = finish - start;
76
77 printf("runTime: %4.2f\n", 1.0*total/1000);
78 printf("freq: %7.0f\n", tsc / (1.0*aperf / (1.0 * mperf)) / total);
79 return 0;
80}
diff --git a/tools/testing/selftests/intel_pstate/msr.c b/tools/testing/selftests/intel_pstate/msr.c
new file mode 100644
index 000000000000..abbbfc84d359
--- /dev/null
+++ b/tools/testing/selftests/intel_pstate/msr.c
@@ -0,0 +1,39 @@
1#include <math.h>
2#include <unistd.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <fcntl.h>
8#include <sys/timeb.h>
9#include <sched.h>
10#include <errno.h>
11
12
13int main(int argc, char **argv) {
14 int cpu, fd;
15 long long msr;
16 char msr_file_name[64];
17
18 if (argc != 2)
19 return 1;
20
21 errno = 0;
22 cpu = strtol(argv[1], (char **) NULL, 10);
23
24 if (errno)
25 return 1;
26
27 sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu);
28 fd = open(msr_file_name, O_RDONLY);
29
30 if (fd == -1) {
31 perror("Failed to open");
32 return 1;
33 }
34
35 pread(fd, &msr, sizeof(msr), 0x199);
36
37 printf("msr 0x199: 0x%llx\n", msr);
38 return 0;
39}
diff --git a/tools/testing/selftests/intel_pstate/run.sh b/tools/testing/selftests/intel_pstate/run.sh
new file mode 100755
index 000000000000..bdaf37e92684
--- /dev/null
+++ b/tools/testing/selftests/intel_pstate/run.sh
@@ -0,0 +1,113 @@
1#!/bin/bash
2#
3# This test runs on Intel x86 based hardware which support the intel_pstate
4# driver. The test checks the frequency settings from the maximum turbo
5# state to the minimum supported frequency, in decrements of 100MHz. The
6# test runs the aperf.c program to put load on each processor.
7#
8# The results are displayed in a table which indicate the "Target" state,
9# or the requested frequency in MHz, the Actual frequency, as read from
10# /proc/cpuinfo, the difference between the Target and Actual frequencies,
11# and the value of MSR 0x199 (MSR_IA32_PERF_CTL) which indicates what
12# pstate the cpu is in, and the value of
13# /sys/devices/system/cpu/intel_pstate/max_perf_pct X maximum turbo state
14#
15# Notes: In some cases several frequency values may be placed in the
16# /tmp/result.X files. This is done on purpose in order to catch cases
17# where the pstate driver may not be working at all. There is the case
18# where, for example, several "similar" frequencies are in the file:
19#
20#
21#/tmp/result.3100:1:cpu MHz : 2899.980
22#/tmp/result.3100:2:cpu MHz : 2900.000
23#/tmp/result.3100:3:msr 0x199: 0x1e00
24#/tmp/result.3100:4:max_perf_pct 94
25#
26# and the test will error out in those cases. The result.X file can be checked
27# for consistency and modified to remove the extra MHz values. The result.X
28# files can be re-evaluated by setting EVALUATE_ONLY to 1 below.
29
30EVALUATE_ONLY=0
31
32max_cpus=$(($(nproc)-1))
33
34# compile programs
35gcc -o aperf aperf.c -lm
36[ $? -ne 0 ] && echo "Problem compiling aperf.c." && exit 1
37gcc -o msr msr.c -lm
38[ $? -ne 0 ] && echo "Problem compiling msr.c." && exit 1
39
40function run_test () {
41
42 file_ext=$1
43 for cpu in `seq 0 $max_cpus`
44 do
45 echo "launching aperf load on $cpu"
46 ./aperf $cpu &
47 done
48
49 echo "sleeping for 5 seconds"
50 sleep 5
51 num_freqs=$(cat /proc/cpuinfo | grep MHz | sort -u | wc -l)
52 if [ $num_freqs -le 2 ]; then
53 cat /proc/cpuinfo | grep MHz | sort -u | tail -1 > /tmp/result.$1
54 else
55 cat /proc/cpuinfo | grep MHz | sort -u > /tmp/result.$1
56 fi
57 ./msr 0 >> /tmp/result.$1
58
59 max_perf_pct=$(cat /sys/devices/system/cpu/intel_pstate/max_perf_pct)
60 echo "max_perf_pct $max_perf_pct" >> /tmp/result.$1
61
62 for job in `jobs -p`
63 do
64 echo "waiting for job id $job"
65 wait $job
66 done
67}
68
69#
70# MAIN (ALL UNITS IN MHZ)
71#
72
73# Get the marketing frequency
74_mkt_freq=$(cat /proc/cpuinfo | grep -m 1 "model name" | awk '{print $NF}')
75_mkt_freq=$(echo $_mkt_freq | tr -d [:alpha:][:punct:])
76mkt_freq=${_mkt_freq}0
77
78# Get the ranges from cpupower
79_min_freq=$(cpupower frequency-info -l | tail -1 | awk ' { print $1 } ')
80min_freq=$(($_min_freq / 1000))
81_max_freq=$(cpupower frequency-info -l | tail -1 | awk ' { print $2 } ')
82max_freq=$(($_max_freq / 1000))
83
84
85for freq in `seq $max_freq -100 $min_freq`
86do
87 echo "Setting maximum frequency to $freq"
88 cpupower frequency-set -g powersave --max=${freq}MHz >& /dev/null
89 [ $EVALUATE_ONLY -eq 0 ] && run_test $freq
90done
91
92echo "=============================================================================="
93
94echo "The marketing frequency of the cpu is $mkt_freq MHz"
95echo "The maximum frequency of the cpu is $max_freq MHz"
96echo "The minimum frequency of the cpu is $min_freq MHz"
97
98cpupower frequency-set -g powersave --max=${max_freq}MHz >& /dev/null
99
100# make a pretty table
101echo "Target Actual Difference MSR(0x199) max_perf_pct"
102for freq in `seq $max_freq -100 $min_freq`
103do
104 result_freq=$(cat /tmp/result.${freq} | grep "cpu MHz" | awk ' { print $4 } ' | awk -F "." ' { print $1 } ')
105 msr=$(cat /tmp/result.${freq} | grep "msr" | awk ' { print $3 } ')
106 max_perf_pct=$(cat /tmp/result.${freq} | grep "max_perf_pct" | awk ' { print $2 } ' )
107 if [ $result_freq -eq $freq ]; then
108 echo " $freq $result_freq 0 $msr $(($max_perf_pct*3300))"
109 else
110 echo " $freq $result_freq $(($result_freq-$freq)) $msr $(($max_perf_pct*$max_freq))"
111 fi
112done
113exit 0
diff --git a/tools/testing/selftests/powerpc/benchmarks/.gitignore b/tools/testing/selftests/powerpc/benchmarks/.gitignore
index b4709ea588c1..6fa673316ac2 100644
--- a/tools/testing/selftests/powerpc/benchmarks/.gitignore
+++ b/tools/testing/selftests/powerpc/benchmarks/.gitignore
@@ -1 +1,2 @@
1gettimeofday 1gettimeofday
2context_switch
diff --git a/tools/testing/selftests/powerpc/benchmarks/Makefile b/tools/testing/selftests/powerpc/benchmarks/Makefile
index 5fa48702070d..912445ff7ce7 100644
--- a/tools/testing/selftests/powerpc/benchmarks/Makefile
+++ b/tools/testing/selftests/powerpc/benchmarks/Makefile
@@ -1,4 +1,4 @@
1TEST_PROGS := gettimeofday 1TEST_PROGS := gettimeofday context_switch
2 2
3CFLAGS += -O2 3CFLAGS += -O2
4 4
@@ -6,6 +6,9 @@ all: $(TEST_PROGS)
6 6
7$(TEST_PROGS): ../harness.c 7$(TEST_PROGS): ../harness.c
8 8
9context_switch: ../utils.c
10context_switch: LDLIBS += -lpthread
11
9include ../../lib.mk 12include ../../lib.mk
10 13
11clean: 14clean:
diff --git a/tools/testing/selftests/powerpc/benchmarks/context_switch.c b/tools/testing/selftests/powerpc/benchmarks/context_switch.c
new file mode 100644
index 000000000000..7b785941adec
--- /dev/null
+++ b/tools/testing/selftests/powerpc/benchmarks/context_switch.c
@@ -0,0 +1,466 @@
1/*
2 * Context switch microbenchmark.
3 *
4 * Copyright (C) 2015 Anton Blanchard <anton@au.ibm.com>, 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 _GNU_SOURCE
13#include <sched.h>
14#include <string.h>
15#include <stdio.h>
16#include <unistd.h>
17#include <stdlib.h>
18#include <getopt.h>
19#include <signal.h>
20#include <assert.h>
21#include <pthread.h>
22#include <limits.h>
23#include <sys/time.h>
24#include <sys/syscall.h>
25#include <sys/types.h>
26#include <sys/shm.h>
27#include <linux/futex.h>
28
29#include "../utils.h"
30
31static unsigned int timeout = 30;
32
33static int touch_vdso;
34struct timeval tv;
35
36static int touch_fp = 1;
37double fp;
38
39static int touch_vector = 1;
40typedef int v4si __attribute__ ((vector_size (16)));
41v4si a, b, c;
42
43#ifdef __powerpc__
44static int touch_altivec = 1;
45
46static void __attribute__((__target__("no-vsx"))) altivec_touch_fn(void)
47{
48 c = a + b;
49}
50#endif
51
52static void touch(void)
53{
54 if (touch_vdso)
55 gettimeofday(&tv, NULL);
56
57 if (touch_fp)
58 fp += 0.1;
59
60#ifdef __powerpc__
61 if (touch_altivec)
62 altivec_touch_fn();
63#endif
64
65 if (touch_vector)
66 c = a + b;
67
68 asm volatile("# %0 %1 %2": : "r"(&tv), "r"(&fp), "r"(&c));
69}
70
71static void start_thread_on(void *(*fn)(void *), void *arg, unsigned long cpu)
72{
73 pthread_t tid;
74 cpu_set_t cpuset;
75 pthread_attr_t attr;
76
77 CPU_ZERO(&cpuset);
78 CPU_SET(cpu, &cpuset);
79
80 pthread_attr_init(&attr);
81
82 if (pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset)) {
83 perror("pthread_attr_setaffinity_np");
84 exit(1);
85 }
86
87 if (pthread_create(&tid, &attr, fn, arg)) {
88 perror("pthread_create");
89 exit(1);
90 }
91}
92
93static void start_process_on(void *(*fn)(void *), void *arg, unsigned long cpu)
94{
95 int pid;
96 cpu_set_t cpuset;
97
98 pid = fork();
99 if (pid == -1) {
100 perror("fork");
101 exit(1);
102 }
103
104 if (pid)
105 return;
106
107 CPU_ZERO(&cpuset);
108 CPU_SET(cpu, &cpuset);
109
110 if (sched_setaffinity(0, sizeof(cpuset), &cpuset)) {
111 perror("sched_setaffinity");
112 exit(1);
113 }
114
115 fn(arg);
116
117 exit(0);
118}
119
120static unsigned long iterations;
121static unsigned long iterations_prev;
122
123static void sigalrm_handler(int junk)
124{
125 unsigned long i = iterations;
126
127 printf("%ld\n", i - iterations_prev);
128 iterations_prev = i;
129
130 if (--timeout == 0)
131 kill(0, SIGUSR1);
132
133 alarm(1);
134}
135
136static void sigusr1_handler(int junk)
137{
138 exit(0);
139}
140
141struct actions {
142 void (*setup)(int, int);
143 void *(*thread1)(void *);
144 void *(*thread2)(void *);
145};
146
147#define READ 0
148#define WRITE 1
149
150static int pipe_fd1[2];
151static int pipe_fd2[2];
152
153static void pipe_setup(int cpu1, int cpu2)
154{
155 if (pipe(pipe_fd1) || pipe(pipe_fd2))
156 exit(1);
157}
158
159static void *pipe_thread1(void *arg)
160{
161 signal(SIGALRM, sigalrm_handler);
162 alarm(1);
163
164 while (1) {
165 assert(read(pipe_fd1[READ], &c, 1) == 1);
166 touch();
167
168 assert(write(pipe_fd2[WRITE], &c, 1) == 1);
169 touch();
170
171 iterations += 2;
172 }
173
174 return NULL;
175}
176
177static void *pipe_thread2(void *arg)
178{
179 while (1) {
180 assert(write(pipe_fd1[WRITE], &c, 1) == 1);
181 touch();
182
183 assert(read(pipe_fd2[READ], &c, 1) == 1);
184 touch();
185 }
186
187 return NULL;
188}
189
190static struct actions pipe_actions = {
191 .setup = pipe_setup,
192 .thread1 = pipe_thread1,
193 .thread2 = pipe_thread2,
194};
195
196static void yield_setup(int cpu1, int cpu2)
197{
198 if (cpu1 != cpu2) {
199 fprintf(stderr, "Both threads must be on the same CPU for yield test\n");
200 exit(1);
201 }
202}
203
204static void *yield_thread1(void *arg)
205{
206 signal(SIGALRM, sigalrm_handler);
207 alarm(1);
208
209 while (1) {
210 sched_yield();
211 touch();
212
213 iterations += 2;
214 }
215
216 return NULL;
217}
218
219static void *yield_thread2(void *arg)
220{
221 while (1) {
222 sched_yield();
223 touch();
224 }
225
226 return NULL;
227}
228
229static struct actions yield_actions = {
230 .setup = yield_setup,
231 .thread1 = yield_thread1,
232 .thread2 = yield_thread2,
233};
234
235static long sys_futex(void *addr1, int op, int val1, struct timespec *timeout,
236 void *addr2, int val3)
237{
238 return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
239}
240
241static unsigned long cmpxchg(unsigned long *p, unsigned long expected,
242 unsigned long desired)
243{
244 unsigned long exp = expected;
245
246 __atomic_compare_exchange_n(p, &exp, desired, 0,
247 __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
248 return exp;
249}
250
251static unsigned long xchg(unsigned long *p, unsigned long val)
252{
253 return __atomic_exchange_n(p, val, __ATOMIC_SEQ_CST);
254}
255
256static int mutex_lock(unsigned long *m)
257{
258 int c;
259
260 c = cmpxchg(m, 0, 1);
261 if (!c)
262 return 0;
263
264 if (c == 1)
265 c = xchg(m, 2);
266
267 while (c) {
268 sys_futex(m, FUTEX_WAIT, 2, NULL, NULL, 0);
269 c = xchg(m, 2);
270 }
271
272 return 0;
273}
274
275static int mutex_unlock(unsigned long *m)
276{
277 if (*m == 2)
278 *m = 0;
279 else if (xchg(m, 0) == 1)
280 return 0;
281
282 sys_futex(m, FUTEX_WAKE, 1, NULL, NULL, 0);
283
284 return 0;
285}
286
287static unsigned long *m1, *m2;
288
289static void futex_setup(int cpu1, int cpu2)
290{
291 int shmid;
292 void *shmaddr;
293
294 shmid = shmget(IPC_PRIVATE, getpagesize(), SHM_R | SHM_W);
295 if (shmid < 0) {
296 perror("shmget");
297 exit(1);
298 }
299
300 shmaddr = shmat(shmid, NULL, 0);
301 if (shmaddr == (char *)-1) {
302 perror("shmat");
303 shmctl(shmid, IPC_RMID, NULL);
304 exit(1);
305 }
306
307 shmctl(shmid, IPC_RMID, NULL);
308
309 m1 = shmaddr;
310 m2 = shmaddr + sizeof(*m1);
311
312 *m1 = 0;
313 *m2 = 0;
314
315 mutex_lock(m1);
316 mutex_lock(m2);
317}
318
319static void *futex_thread1(void *arg)
320{
321 signal(SIGALRM, sigalrm_handler);
322 alarm(1);
323
324 while (1) {
325 mutex_lock(m2);
326 mutex_unlock(m1);
327
328 iterations += 2;
329 }
330
331 return NULL;
332}
333
334static void *futex_thread2(void *arg)
335{
336 while (1) {
337 mutex_unlock(m2);
338 mutex_lock(m1);
339 }
340
341 return NULL;
342}
343
344static struct actions futex_actions = {
345 .setup = futex_setup,
346 .thread1 = futex_thread1,
347 .thread2 = futex_thread2,
348};
349
350static int processes;
351
352static struct option options[] = {
353 { "test", required_argument, 0, 't' },
354 { "process", no_argument, &processes, 1 },
355 { "timeout", required_argument, 0, 's' },
356 { "vdso", no_argument, &touch_vdso, 1 },
357 { "no-fp", no_argument, &touch_fp, 0 },
358#ifdef __powerpc__
359 { "no-altivec", no_argument, &touch_altivec, 0 },
360#endif
361 { "no-vector", no_argument, &touch_vector, 0 },
362 { 0, },
363};
364
365static void usage(void)
366{
367 fprintf(stderr, "Usage: context_switch2 <options> CPU1 CPU2\n\n");
368 fprintf(stderr, "\t\t--test=X\tpipe, futex or yield (default)\n");
369 fprintf(stderr, "\t\t--process\tUse processes (default threads)\n");
370 fprintf(stderr, "\t\t--timeout=X\tDuration in seconds to run (default 30)\n");
371 fprintf(stderr, "\t\t--vdso\t\ttouch VDSO\n");
372 fprintf(stderr, "\t\t--fp\t\ttouch FP\n");
373#ifdef __powerpc__
374 fprintf(stderr, "\t\t--altivec\ttouch altivec\n");
375#endif
376 fprintf(stderr, "\t\t--vector\ttouch vector\n");
377}
378
379int main(int argc, char *argv[])
380{
381 signed char c;
382 struct actions *actions = &yield_actions;
383 int cpu1;
384 int cpu2;
385 static void (*start_fn)(void *(*fn)(void *), void *arg, unsigned long cpu);
386
387 while (1) {
388 int option_index = 0;
389
390 c = getopt_long(argc, argv, "", options, &option_index);
391
392 if (c == -1)
393 break;
394
395 switch (c) {
396 case 0:
397 if (options[option_index].flag != 0)
398 break;
399
400 usage();
401 exit(1);
402 break;
403
404 case 't':
405 if (!strcmp(optarg, "pipe")) {
406 actions = &pipe_actions;
407 } else if (!strcmp(optarg, "yield")) {
408 actions = &yield_actions;
409 } else if (!strcmp(optarg, "futex")) {
410 actions = &futex_actions;
411 } else {
412 usage();
413 exit(1);
414 }
415 break;
416
417 case 's':
418 timeout = atoi(optarg);
419 break;
420
421 default:
422 usage();
423 exit(1);
424 }
425 }
426
427 if (processes)
428 start_fn = start_process_on;
429 else
430 start_fn = start_thread_on;
431
432 if (((argc - optind) != 2)) {
433 cpu1 = cpu2 = pick_online_cpu();
434 } else {
435 cpu1 = atoi(argv[optind++]);
436 cpu2 = atoi(argv[optind++]);
437 }
438
439 printf("Using %s with ", processes ? "processes" : "threads");
440
441 if (actions == &pipe_actions)
442 printf("pipe");
443 else if (actions == &yield_actions)
444 printf("yield");
445 else
446 printf("futex");
447
448 printf(" on cpus %d/%d touching FP:%s altivec:%s vector:%s vdso:%s\n",
449 cpu1, cpu2, touch_fp ? "yes" : "no", touch_altivec ? "yes" : "no",
450 touch_vector ? "yes" : "no", touch_vdso ? "yes" : "no");
451
452 /* Create a new process group so we can signal everyone for exit */
453 setpgid(getpid(), getpid());
454
455 signal(SIGUSR1, sigusr1_handler);
456
457 actions->setup(cpu1, cpu2);
458
459 start_fn(actions->thread1, NULL, cpu1);
460 start_fn(actions->thread2, NULL, cpu2);
461
462 while (1)
463 sleep(3600);
464
465 return 0;
466}
diff --git a/tools/testing/selftests/powerpc/dscr/dscr_inherit_exec_test.c b/tools/testing/selftests/powerpc/dscr/dscr_inherit_exec_test.c
index 8265504de571..08a8b95e3bc1 100644
--- a/tools/testing/selftests/powerpc/dscr/dscr_inherit_exec_test.c
+++ b/tools/testing/selftests/powerpc/dscr/dscr_inherit_exec_test.c
@@ -60,14 +60,6 @@ int dscr_inherit_exec(void)
60 else 60 else
61 set_dscr(dscr); 61 set_dscr(dscr);
62 62
63 /*
64 * XXX: Force a context switch out so that DSCR
65 * current value is copied into the thread struct
66 * which is required for the child to inherit the
67 * changed value.
68 */
69 sleep(1);
70
71 pid = fork(); 63 pid = fork();
72 if (pid == -1) { 64 if (pid == -1) {
73 perror("fork() failed"); 65 perror("fork() failed");
diff --git a/tools/testing/selftests/powerpc/dscr/dscr_inherit_test.c b/tools/testing/selftests/powerpc/dscr/dscr_inherit_test.c
index 4e414caf7f40..3e5a6d195e9a 100644
--- a/tools/testing/selftests/powerpc/dscr/dscr_inherit_test.c
+++ b/tools/testing/selftests/powerpc/dscr/dscr_inherit_test.c
@@ -40,14 +40,6 @@ int dscr_inherit(void)
40 else 40 else
41 set_dscr(dscr); 41 set_dscr(dscr);
42 42
43 /*
44 * XXX: Force a context switch out so that DSCR
45 * current value is copied into the thread struct
46 * which is required for the child to inherit the
47 * changed value.
48 */
49 sleep(1);
50
51 pid = fork(); 43 pid = fork();
52 if (pid == -1) { 44 if (pid == -1) {
53 perror("fork() failed"); 45 perror("fork() failed");
diff --git a/tools/testing/selftests/powerpc/harness.c b/tools/testing/selftests/powerpc/harness.c
index f7997affd143..52f9be7f61f0 100644
--- a/tools/testing/selftests/powerpc/harness.c
+++ b/tools/testing/selftests/powerpc/harness.c
@@ -116,46 +116,3 @@ int test_harness(int (test_function)(void), char *name)
116 116
117 return rc; 117 return rc;
118} 118}
119
120static char auxv[4096];
121
122void *get_auxv_entry(int type)
123{
124 ElfW(auxv_t) *p;
125 void *result;
126 ssize_t num;
127 int fd;
128
129 fd = open("/proc/self/auxv", O_RDONLY);
130 if (fd == -1) {
131 perror("open");
132 return NULL;
133 }
134
135 result = NULL;
136
137 num = read(fd, auxv, sizeof(auxv));
138 if (num < 0) {
139 perror("read");
140 goto out;
141 }
142
143 if (num > sizeof(auxv)) {
144 printf("Overflowed auxv buffer\n");
145 goto out;
146 }
147
148 p = (ElfW(auxv_t) *)auxv;
149
150 while (p->a_type != AT_NULL) {
151 if (p->a_type == type) {
152 result = (void *)p->a_un.a_val;
153 break;
154 }
155
156 p++;
157 }
158out:
159 close(fd);
160 return result;
161}
diff --git a/tools/testing/selftests/powerpc/pmu/Makefile b/tools/testing/selftests/powerpc/pmu/Makefile
index a9099d9f8f39..ac41a7177f2e 100644
--- a/tools/testing/selftests/powerpc/pmu/Makefile
+++ b/tools/testing/selftests/powerpc/pmu/Makefile
@@ -2,7 +2,7 @@ noarg:
2 $(MAKE) -C ../ 2 $(MAKE) -C ../
3 3
4TEST_PROGS := count_instructions l3_bank_test per_event_excludes 4TEST_PROGS := count_instructions l3_bank_test per_event_excludes
5EXTRA_SOURCES := ../harness.c event.c lib.c 5EXTRA_SOURCES := ../harness.c event.c lib.c ../utils.c
6 6
7all: $(TEST_PROGS) ebb 7all: $(TEST_PROGS) ebb
8 8
@@ -12,6 +12,8 @@ $(TEST_PROGS): $(EXTRA_SOURCES)
12count_instructions: loop.S count_instructions.c $(EXTRA_SOURCES) 12count_instructions: loop.S count_instructions.c $(EXTRA_SOURCES)
13 $(CC) $(CFLAGS) -m64 -o $@ $^ 13 $(CC) $(CFLAGS) -m64 -o $@ $^
14 14
15per_event_excludes: ../utils.c
16
15include ../../lib.mk 17include ../../lib.mk
16 18
17DEFAULT_RUN_TESTS := $(RUN_TESTS) 19DEFAULT_RUN_TESTS := $(RUN_TESTS)
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/Makefile b/tools/testing/selftests/powerpc/pmu/ebb/Makefile
index 5cdc9dbf2b27..8d2279c4bb4b 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/Makefile
+++ b/tools/testing/selftests/powerpc/pmu/ebb/Makefile
@@ -18,7 +18,8 @@ TEST_PROGS := reg_access_test event_attributes_test cycles_test \
18 18
19all: $(TEST_PROGS) 19all: $(TEST_PROGS)
20 20
21$(TEST_PROGS): ../../harness.c ../event.c ../lib.c ebb.c ebb_handler.S trace.c busy_loop.S 21$(TEST_PROGS): ../../harness.c ../../utils.c ../event.c ../lib.c \
22 ebb.c ebb_handler.S trace.c busy_loop.S
22 23
23instruction_count_test: ../loop.S 24instruction_count_test: ../loop.S
24 25
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
index 9729d9f90218..e67452f1bcff 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
+++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
@@ -13,7 +13,6 @@
13#include <stdlib.h> 13#include <stdlib.h>
14#include <string.h> 14#include <string.h>
15#include <sys/ioctl.h> 15#include <sys/ioctl.h>
16#include <linux/auxvec.h>
17 16
18#include "trace.h" 17#include "trace.h"
19#include "reg.h" 18#include "reg.h"
@@ -324,7 +323,7 @@ bool ebb_is_supported(void)
324{ 323{
325#ifdef PPC_FEATURE2_EBB 324#ifdef PPC_FEATURE2_EBB
326 /* EBB requires at least POWER8 */ 325 /* EBB requires at least POWER8 */
327 return ((long)get_auxv_entry(AT_HWCAP2) & PPC_FEATURE2_EBB); 326 return have_hwcap2(PPC_FEATURE2_EBB);
328#else 327#else
329 return false; 328 return false;
330#endif 329#endif
diff --git a/tools/testing/selftests/powerpc/pmu/lib.c b/tools/testing/selftests/powerpc/pmu/lib.c
index a07104c2afe6..a361ad3334ce 100644
--- a/tools/testing/selftests/powerpc/pmu/lib.c
+++ b/tools/testing/selftests/powerpc/pmu/lib.c
@@ -15,32 +15,6 @@
15#include "lib.h" 15#include "lib.h"
16 16
17 17
18int pick_online_cpu(void)
19{
20 cpu_set_t mask;
21 int cpu;
22
23 CPU_ZERO(&mask);
24
25 if (sched_getaffinity(0, sizeof(mask), &mask)) {
26 perror("sched_getaffinity");
27 return -1;
28 }
29
30 /* We prefer a primary thread, but skip 0 */
31 for (cpu = 8; cpu < CPU_SETSIZE; cpu += 8)
32 if (CPU_ISSET(cpu, &mask))
33 return cpu;
34
35 /* Search for anything, but in reverse */
36 for (cpu = CPU_SETSIZE - 1; cpu >= 0; cpu--)
37 if (CPU_ISSET(cpu, &mask))
38 return cpu;
39
40 printf("No cpus in affinity mask?!\n");
41 return -1;
42}
43
44int bind_to_cpu(int cpu) 18int bind_to_cpu(int cpu)
45{ 19{
46 cpu_set_t mask; 20 cpu_set_t mask;
diff --git a/tools/testing/selftests/powerpc/pmu/lib.h b/tools/testing/selftests/powerpc/pmu/lib.h
index ca5d72ae3be6..0213af4ff332 100644
--- a/tools/testing/selftests/powerpc/pmu/lib.h
+++ b/tools/testing/selftests/powerpc/pmu/lib.h
@@ -19,7 +19,6 @@ union pipe {
19 int fds[2]; 19 int fds[2];
20}; 20};
21 21
22extern int pick_online_cpu(void);
23extern int bind_to_cpu(int cpu); 22extern int bind_to_cpu(int cpu);
24extern int kill_child_and_wait(pid_t child_pid); 23extern int kill_child_and_wait(pid_t child_pid);
25extern int wait_for_child(pid_t child_pid); 24extern int wait_for_child(pid_t child_pid);
diff --git a/tools/testing/selftests/powerpc/scripts/hmi.sh b/tools/testing/selftests/powerpc/scripts/hmi.sh
new file mode 100755
index 000000000000..83fb253ae3bd
--- /dev/null
+++ b/tools/testing/selftests/powerpc/scripts/hmi.sh
@@ -0,0 +1,89 @@
1#!/bin/sh
2#
3# Copyright 2015, Daniel Axtens, IBM Corporation
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; version 2 of the License.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13
14
15# do we have ./getscom, ./putscom?
16if [ -x ./getscom ] && [ -x ./putscom ]; then
17 GETSCOM=./getscom
18 PUTSCOM=./putscom
19elif which getscom > /dev/null; then
20 GETSCOM=$(which getscom)
21 PUTSCOM=$(which putscom)
22else
23 cat <<EOF
24Can't find getscom/putscom in . or \$PATH.
25See https://github.com/open-power/skiboot.
26The tool is in external/xscom-utils
27EOF
28 exit 1
29fi
30
31# We will get 8 HMI events per injection
32# todo: deal with things being offline
33expected_hmis=8
34COUNT_HMIS() {
35 dmesg | grep -c 'Harmless Hypervisor Maintenance interrupt'
36}
37
38# massively expand snooze delay, allowing injection on all cores
39ppc64_cpu --smt-snooze-delay=1000000000
40
41# when we exit, restore it
42trap "ppc64_cpu --smt-snooze-delay=100" 0 1
43
44# for each chip+core combination
45# todo - less fragile parsing
46egrep -o 'OCC: Chip [0-9a-f]+ Core [0-9a-f]' < /sys/firmware/opal/msglog |
47while read chipcore; do
48 chip=$(echo "$chipcore"|awk '{print $3}')
49 core=$(echo "$chipcore"|awk '{print $5}')
50 fir="0x1${core}013100"
51
52 # verify that Core FIR is zero as expected
53 if [ "$($GETSCOM -c 0x${chip} $fir)" != 0 ]; then
54 echo "FIR was not zero before injection for chip $chip, core $core. Aborting!"
55 echo "Result of $GETSCOM -c 0x${chip} $fir:"
56 $GETSCOM -c 0x${chip} $fir
57 echo "If you get a -5 error, the core may be in idle state. Try stress-ng."
58 echo "Otherwise, try $PUTSCOM -c 0x${chip} $fir 0"
59 exit 1
60 fi
61
62 # keep track of the number of HMIs handled
63 old_hmis=$(COUNT_HMIS)
64
65 # do injection, adding a marker to dmesg for clarity
66 echo "Injecting HMI on core $core, chip $chip" | tee /dev/kmsg
67 # inject a RegFile recoverable error
68 if ! $PUTSCOM -c 0x${chip} $fir 2000000000000000 > /dev/null; then
69 echo "Error injecting. Aborting!"
70 exit 1
71 fi
72
73 # now we want to wait for all the HMIs to be processed
74 # we expect one per thread on the core
75 i=0;
76 new_hmis=$(COUNT_HMIS)
77 while [ $new_hmis -lt $((old_hmis + expected_hmis)) ] && [ $i -lt 12 ]; do
78 echo "Seen $((new_hmis - old_hmis)) HMI(s) out of $expected_hmis expected, sleeping"
79 sleep 5;
80 i=$((i + 1))
81 new_hmis=$(COUNT_HMIS)
82 done
83 if [ $i = 12 ]; then
84 echo "Haven't seen expected $expected_hmis recoveries after 1 min. Aborting."
85 exit 1
86 fi
87 echo "Processed $expected_hmis events; presumed success. Check dmesg."
88 echo ""
89done
diff --git a/tools/testing/selftests/powerpc/tm/.gitignore b/tools/testing/selftests/powerpc/tm/.gitignore
index 2699635d2cd9..7d0f14b8cb2e 100644
--- a/tools/testing/selftests/powerpc/tm/.gitignore
+++ b/tools/testing/selftests/powerpc/tm/.gitignore
@@ -1,2 +1,5 @@
1tm-resched-dscr 1tm-resched-dscr
2tm-syscall 2tm-syscall
3tm-signal-msr-resv
4tm-signal-stack
5tm-vmxcopy
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 4bea62a319dc..737f72c964e6 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -1,8 +1,8 @@
1TEST_PROGS := tm-resched-dscr tm-syscall 1TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack tm-vmxcopy
2 2
3all: $(TEST_PROGS) 3all: $(TEST_PROGS)
4 4
5$(TEST_PROGS): ../harness.c 5$(TEST_PROGS): ../harness.c ../utils.c
6 6
7tm-syscall: tm-syscall-asm.S 7tm-syscall: tm-syscall-asm.S
8tm-syscall: CFLAGS += -mhtm -I../../../../../usr/include 8tm-syscall: CFLAGS += -mhtm -I../../../../../usr/include
diff --git a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
index 42d4c8caad81..8fde93d6021f 100644
--- a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
+++ b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
@@ -29,6 +29,7 @@
29#include <asm/tm.h> 29#include <asm/tm.h>
30 30
31#include "utils.h" 31#include "utils.h"
32#include "tm.h"
32 33
33#define TBEGIN ".long 0x7C00051D ;" 34#define TBEGIN ".long 0x7C00051D ;"
34#define TEND ".long 0x7C00055D ;" 35#define TEND ".long 0x7C00055D ;"
@@ -42,6 +43,8 @@ int test_body(void)
42{ 43{
43 uint64_t rv, dscr1 = 1, dscr2, texasr; 44 uint64_t rv, dscr1 = 1, dscr2, texasr;
44 45
46 SKIP_IF(!have_htm());
47
45 printf("Check DSCR TM context switch: "); 48 printf("Check DSCR TM context switch: ");
46 fflush(stdout); 49 fflush(stdout);
47 for (;;) { 50 for (;;) {
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-msr-resv.c b/tools/testing/selftests/powerpc/tm/tm-signal-msr-resv.c
new file mode 100644
index 000000000000..d86653f282b1
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-msr-resv.c
@@ -0,0 +1,74 @@
1/*
2 * Copyright 2015, Michael Neuling, IBM Corp.
3 * Licensed under GPLv2.
4 *
5 * Test the kernel's signal return code to ensure that it doesn't
6 * crash when both the transactional and suspend MSR bits are set in
7 * the signal context.
8 *
9 * For this test, we send ourselves a SIGUSR1. In the SIGUSR1 handler
10 * we modify the signal context to set both MSR TM S and T bits (which
11 * is "reserved" by the PowerISA). When we return from the signal
12 * handler (implicit sigreturn), the kernel should detect reserved MSR
13 * value and send us with a SIGSEGV.
14 */
15
16#include <stdlib.h>
17#include <stdio.h>
18#include <signal.h>
19#include <unistd.h>
20
21#include "utils.h"
22#include "tm.h"
23
24int segv_expected = 0;
25
26void signal_segv(int signum)
27{
28 if (segv_expected && (signum == SIGSEGV))
29 _exit(0);
30 _exit(1);
31}
32
33void signal_usr1(int signum, siginfo_t *info, void *uc)
34{
35 ucontext_t *ucp = uc;
36
37 /* Link tm checkpointed context to normal context */
38 ucp->uc_link = ucp;
39 /* Set all TM bits so that the context is now invalid */
40#ifdef __powerpc64__
41 ucp->uc_mcontext.gp_regs[PT_MSR] |= (7ULL << 32);
42#else
43 ucp->uc_mcontext.regs->gpr[PT_MSR] |= (7ULL);
44#endif
45 /* Should segv on return becuase of invalid context */
46 segv_expected = 1;
47}
48
49int tm_signal_msr_resv()
50{
51 struct sigaction act;
52
53 SKIP_IF(!have_htm());
54
55 act.sa_sigaction = signal_usr1;
56 sigemptyset(&act.sa_mask);
57 act.sa_flags = SA_SIGINFO;
58 if (sigaction(SIGUSR1, &act, NULL) < 0) {
59 perror("sigaction sigusr1");
60 exit(1);
61 }
62 if (signal(SIGSEGV, signal_segv) == SIG_ERR)
63 exit(1);
64
65 raise(SIGUSR1);
66
67 /* We shouldn't get here as we exit in the segv handler */
68 return 1;
69}
70
71int main(void)
72{
73 return test_harness(tm_signal_msr_resv, "tm_signal_msr_resv");
74}
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-stack.c b/tools/testing/selftests/powerpc/tm/tm-signal-stack.c
new file mode 100644
index 000000000000..e44a238c1d77
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-stack.c
@@ -0,0 +1,76 @@
1/*
2 * Copyright 2015, Michael Neuling, IBM Corp.
3 * Licensed under GPLv2.
4 *
5 * Test the kernel's signal delievery code to ensure that we don't
6 * trelaim twice in the kernel signal delivery code. This can happen
7 * if we trigger a signal when in a transaction and the stack pointer
8 * is bogus.
9 *
10 * This test case registers a SEGV handler, sets the stack pointer
11 * (r1) to NULL, starts a transaction and then generates a SEGV. The
12 * SEGV should be handled but we exit here as the stack pointer is
13 * invalid and hance we can't sigreturn. We only need to check that
14 * this flow doesn't crash the kernel.
15 */
16
17#include <unistd.h>
18#include <sys/types.h>
19#include <sys/wait.h>
20#include <stdlib.h>
21#include <stdio.h>
22#include <signal.h>
23
24#include "utils.h"
25#include "tm.h"
26
27void signal_segv(int signum)
28{
29 /* This should never actually run since stack is foobar */
30 exit(1);
31}
32
33int tm_signal_stack()
34{
35 int pid;
36
37 SKIP_IF(!have_htm());
38
39 pid = fork();
40 if (pid < 0)
41 exit(1);
42
43 if (pid) { /* Parent */
44 /*
45 * It's likely the whole machine will crash here so if
46 * the child ever exits, we are good.
47 */
48 wait(NULL);
49 return 0;
50 }
51
52 /*
53 * The flow here is:
54 * 1) register a signal handler (so signal delievery occurs)
55 * 2) make stack pointer (r1) = NULL
56 * 3) start transaction
57 * 4) cause segv
58 */
59 if (signal(SIGSEGV, signal_segv) == SIG_ERR)
60 exit(1);
61 asm volatile("li 1, 0 ;" /* stack ptr == NULL */
62 "1:"
63 ".long 0x7C00051D ;" /* tbegin */
64 "beq 1b ;" /* retry forever */
65 ".long 0x7C0005DD ; ;" /* tsuspend */
66 "ld 2, 0(1) ;" /* trigger segv" */
67 : : : "memory");
68
69 /* This should never get here due to above segv */
70 return 1;
71}
72
73int main(void)
74{
75 return test_harness(tm_signal_stack, "tm_signal_stack");
76}
diff --git a/tools/testing/selftests/powerpc/tm/tm-syscall.c b/tools/testing/selftests/powerpc/tm/tm-syscall.c
index e835bf7ec7ae..60560cb20e38 100644
--- a/tools/testing/selftests/powerpc/tm/tm-syscall.c
+++ b/tools/testing/selftests/powerpc/tm/tm-syscall.c
@@ -13,12 +13,11 @@
13#include <unistd.h> 13#include <unistd.h>
14#include <sys/syscall.h> 14#include <sys/syscall.h>
15#include <asm/tm.h> 15#include <asm/tm.h>
16#include <asm/cputable.h>
17#include <linux/auxvec.h>
18#include <sys/time.h> 16#include <sys/time.h>
19#include <stdlib.h> 17#include <stdlib.h>
20 18
21#include "utils.h" 19#include "utils.h"
20#include "tm.h"
22 21
23extern int getppid_tm_active(void); 22extern int getppid_tm_active(void);
24extern int getppid_tm_suspended(void); 23extern int getppid_tm_suspended(void);
@@ -77,16 +76,6 @@ pid_t getppid_tm(bool suspend)
77 exit(-1); 76 exit(-1);
78} 77}
79 78
80static inline bool have_htm_nosc(void)
81{
82#ifdef PPC_FEATURE2_HTM_NOSC
83 return ((long)get_auxv_entry(AT_HWCAP2) & PPC_FEATURE2_HTM_NOSC);
84#else
85 printf("PPC_FEATURE2_HTM_NOSC not defined, can't check AT_HWCAP2\n");
86 return false;
87#endif
88}
89
90int tm_syscall(void) 79int tm_syscall(void)
91{ 80{
92 unsigned count = 0; 81 unsigned count = 0;
diff --git a/tools/testing/selftests/powerpc/tm/tm-vmxcopy.c b/tools/testing/selftests/powerpc/tm/tm-vmxcopy.c
new file mode 100644
index 000000000000..0274de7b11f3
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-vmxcopy.c
@@ -0,0 +1,103 @@
1/*
2 * Copyright 2015, Michael Neuling, IBM Corp.
3 * Licensed under GPLv2.
4 *
5 * Original: Michael Neuling 4/12/2013
6 * Edited: Rashmica Gupta 4/12/2015
7 *
8 * See if the altivec state is leaked out of an aborted transaction due to
9 * kernel vmx copy loops.
10 *
11 * When the transaction aborts, VSR values should rollback to the values
12 * they held before the transaction commenced. Using VSRs while transaction
13 * is suspended should not affect the checkpointed values.
14 *
15 * (1) write A to a VSR
16 * (2) start transaction
17 * (3) suspend transaction
18 * (4) change the VSR to B
19 * (5) trigger kernel vmx copy loop
20 * (6) abort transaction
21 * (7) check that the VSR value is A
22 */
23
24#include <inttypes.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <unistd.h>
28#include <sys/mman.h>
29#include <string.h>
30#include <assert.h>
31
32#include "tm.h"
33#include "utils.h"
34
35int test_vmxcopy()
36{
37 long double vecin = 1.3;
38 long double vecout;
39 unsigned long pgsize = getpagesize();
40 int i;
41 int fd;
42 int size = pgsize*16;
43 char tmpfile[] = "/tmp/page_faultXXXXXX";
44 char buf[pgsize];
45 char *a;
46 uint64_t aborted = 0;
47
48 SKIP_IF(!have_htm());
49
50 fd = mkstemp(tmpfile);
51 assert(fd >= 0);
52
53 memset(buf, 0, pgsize);
54 for (i = 0; i < size; i += pgsize)
55 assert(write(fd, buf, pgsize) == pgsize);
56
57 unlink(tmpfile);
58
59 a = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
60 assert(a != MAP_FAILED);
61
62 asm __volatile__(
63 "lxvd2x 40,0,%[vecinptr];" /* set 40 to initial value*/
64 "tbegin.;"
65 "beq 3f;"
66 "tsuspend.;"
67 "xxlxor 40,40,40;" /* set 40 to 0 */
68 "std 5, 0(%[map]);" /* cause kernel vmx copy page */
69 "tabort. 0;"
70 "tresume.;"
71 "tend.;"
72 "li %[res], 0;"
73 "b 5f;"
74
75 /* Abort handler */
76 "3:;"
77 "li %[res], 1;"
78
79 "5:;"
80 "stxvd2x 40,0,%[vecoutptr];"
81 : [res]"=r"(aborted)
82 : [vecinptr]"r"(&vecin),
83 [vecoutptr]"r"(&vecout),
84 [map]"r"(a)
85 : "memory", "r0", "r3", "r4", "r5", "r6", "r7");
86
87 if (aborted && (vecin != vecout)){
88 printf("FAILED: vector state leaked on abort %f != %f\n",
89 (double)vecin, (double)vecout);
90 return 1;
91 }
92
93 munmap(a, size);
94
95 close(fd);
96
97 return 0;
98}
99
100int main(void)
101{
102 return test_harness(test_vmxcopy, "tm_vmxcopy");
103}
diff --git a/tools/testing/selftests/powerpc/tm/tm.h b/tools/testing/selftests/powerpc/tm/tm.h
new file mode 100644
index 000000000000..24144b25772c
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm.h
@@ -0,0 +1,34 @@
1/*
2 * Copyright 2015, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#ifndef _SELFTESTS_POWERPC_TM_TM_H
7#define _SELFTESTS_POWERPC_TM_TM_H
8
9#include <stdbool.h>
10#include <asm/cputable.h>
11
12#include "../utils.h"
13
14static inline bool have_htm(void)
15{
16#ifdef PPC_FEATURE2_HTM
17 return have_hwcap2(PPC_FEATURE2_HTM);
18#else
19 printf("PPC_FEATURE2_HTM not defined, can't check AT_HWCAP2\n");
20 return false;
21#endif
22}
23
24static inline bool have_htm_nosc(void)
25{
26#ifdef PPC_FEATURE2_HTM_NOSC
27 return have_hwcap2(PPC_FEATURE2_HTM_NOSC);
28#else
29 printf("PPC_FEATURE2_HTM_NOSC not defined, can't check AT_HWCAP2\n");
30 return false;
31#endif
32}
33
34#endif /* _SELFTESTS_POWERPC_TM_TM_H */
diff --git a/tools/testing/selftests/powerpc/utils.c b/tools/testing/selftests/powerpc/utils.c
new file mode 100644
index 000000000000..dcf74184bfd0
--- /dev/null
+++ b/tools/testing/selftests/powerpc/utils.c
@@ -0,0 +1,87 @@
1/*
2 * Copyright 2013-2015, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#define _GNU_SOURCE /* For CPU_ZERO etc. */
7
8#include <elf.h>
9#include <errno.h>
10#include <fcntl.h>
11#include <link.h>
12#include <sched.h>
13#include <stdio.h>
14#include <sys/stat.h>
15#include <sys/types.h>
16#include <unistd.h>
17
18#include "utils.h"
19
20static char auxv[4096];
21
22void *get_auxv_entry(int type)
23{
24 ElfW(auxv_t) *p;
25 void *result;
26 ssize_t num;
27 int fd;
28
29 fd = open("/proc/self/auxv", O_RDONLY);
30 if (fd == -1) {
31 perror("open");
32 return NULL;
33 }
34
35 result = NULL;
36
37 num = read(fd, auxv, sizeof(auxv));
38 if (num < 0) {
39 perror("read");
40 goto out;
41 }
42
43 if (num > sizeof(auxv)) {
44 printf("Overflowed auxv buffer\n");
45 goto out;
46 }
47
48 p = (ElfW(auxv_t) *)auxv;
49
50 while (p->a_type != AT_NULL) {
51 if (p->a_type == type) {
52 result = (void *)p->a_un.a_val;
53 break;
54 }
55
56 p++;
57 }
58out:
59 close(fd);
60 return result;
61}
62
63int pick_online_cpu(void)
64{
65 cpu_set_t mask;
66 int cpu;
67
68 CPU_ZERO(&mask);
69
70 if (sched_getaffinity(0, sizeof(mask), &mask)) {
71 perror("sched_getaffinity");
72 return -1;
73 }
74
75 /* We prefer a primary thread, but skip 0 */
76 for (cpu = 8; cpu < CPU_SETSIZE; cpu += 8)
77 if (CPU_ISSET(cpu, &mask))
78 return cpu;
79
80 /* Search for anything, but in reverse */
81 for (cpu = CPU_SETSIZE - 1; cpu >= 0; cpu--)
82 if (CPU_ISSET(cpu, &mask))
83 return cpu;
84
85 printf("No cpus in affinity mask?!\n");
86 return -1;
87}
diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h
index b7d41086bb0a..175ac6ad10dd 100644
--- a/tools/testing/selftests/powerpc/utils.h
+++ b/tools/testing/selftests/powerpc/utils.h
@@ -8,6 +8,7 @@
8 8
9#include <stdint.h> 9#include <stdint.h>
10#include <stdbool.h> 10#include <stdbool.h>
11#include <linux/auxvec.h>
11 12
12/* Avoid headaches with PRI?64 - just use %ll? always */ 13/* Avoid headaches with PRI?64 - just use %ll? always */
13typedef unsigned long long u64; 14typedef unsigned long long u64;
@@ -21,6 +22,12 @@ typedef uint8_t u8;
21 22
22int test_harness(int (test_function)(void), char *name); 23int test_harness(int (test_function)(void), char *name);
23extern void *get_auxv_entry(int type); 24extern void *get_auxv_entry(int type);
25int pick_online_cpu(void);
26
27static inline bool have_hwcap2(unsigned long ftr2)
28{
29 return ((unsigned long)get_auxv_entry(AT_HWCAP2) & ftr2) == ftr2;
30}
24 31
25/* Yes, this is evil */ 32/* Yes, this is evil */
26#define FAIL_IF(x) \ 33#define FAIL_IF(x) \
diff --git a/tools/testing/selftests/ptrace/.gitignore b/tools/testing/selftests/ptrace/.gitignore
new file mode 100644
index 000000000000..b3e59d41fd82
--- /dev/null
+++ b/tools/testing/selftests/ptrace/.gitignore
@@ -0,0 +1 @@
peeksiginfo
diff --git a/tools/testing/selftests/seccomp/test_harness.h b/tools/testing/selftests/seccomp/test_harness.h
index fb2841601f2f..a786c69c7584 100644
--- a/tools/testing/selftests/seccomp/test_harness.h
+++ b/tools/testing/selftests/seccomp/test_harness.h
@@ -42,6 +42,7 @@
42#define TEST_HARNESS_H_ 42#define TEST_HARNESS_H_
43 43
44#define _GNU_SOURCE 44#define _GNU_SOURCE
45#include <stdint.h>
45#include <stdio.h> 46#include <stdio.h>
46#include <stdlib.h> 47#include <stdlib.h>
47#include <string.h> 48#include <string.h>
@@ -370,8 +371,8 @@
370 __typeof__(_expected) __exp = (_expected); \ 371 __typeof__(_expected) __exp = (_expected); \
371 __typeof__(_seen) __seen = (_seen); \ 372 __typeof__(_seen) __seen = (_seen); \
372 if (!(__exp _t __seen)) { \ 373 if (!(__exp _t __seen)) { \
373 unsigned long long __exp_print = (unsigned long long)__exp; \ 374 unsigned long long __exp_print = (uintptr_t)__exp; \
374 unsigned long long __seen_print = (unsigned long long)__seen; \ 375 unsigned long long __seen_print = (uintptr_t)__seen; \
375 __TH_LOG("Expected %s (%llu) %s %s (%llu)", \ 376 __TH_LOG("Expected %s (%llu) %s %s (%llu)", \
376 #_expected, __exp_print, #_t, \ 377 #_expected, __exp_print, #_t, \
377 #_seen, __seen_print); \ 378 #_seen, __seen_print); \
diff --git a/tools/testing/selftests/timers/.gitignore b/tools/testing/selftests/timers/.gitignore
index ced998151bc4..68f3fc71ac44 100644
--- a/tools/testing/selftests/timers/.gitignore
+++ b/tools/testing/selftests/timers/.gitignore
@@ -16,3 +16,4 @@ set-timer-lat
16skew_consistency 16skew_consistency
17threadtest 17threadtest
18valid-adjtimex 18valid-adjtimex
19adjtick
diff --git a/tools/testing/selftests/vm/.gitignore b/tools/testing/selftests/vm/.gitignore
index ff1bb16cec4f..a937a9d26b60 100644
--- a/tools/testing/selftests/vm/.gitignore
+++ b/tools/testing/selftests/vm/.gitignore
@@ -2,3 +2,8 @@ hugepage-mmap
2hugepage-shm 2hugepage-shm
3map_hugetlb 3map_hugetlb
4thuge-gen 4thuge-gen
5compaction_test
6mlock2-tests
7on-fault-limit
8transhuge-stress
9userfaultfd
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index eabcff411984..d0c473f65850 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -4,9 +4,11 @@ include ../lib.mk
4 4
5.PHONY: all all_32 all_64 warn_32bit_failure clean 5.PHONY: all all_32 all_64 warn_32bit_failure clean
6 6
7TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs ldt_gdt syscall_nt ptrace_syscall 7TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall
8TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn test_syscall_vdso unwind_vdso \ 8TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn test_syscall_vdso unwind_vdso \
9 test_FCMOV test_FCOMI test_FISTTP 9 test_FCMOV test_FCOMI test_FISTTP \
10 ldt_gdt \
11 vdso_restorer
10 12
11TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) 13TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY)
12BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32) 14BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32)
diff --git a/tools/testing/selftests/x86/vdso_restorer.c b/tools/testing/selftests/x86/vdso_restorer.c
new file mode 100644
index 000000000000..cb038424a403
--- /dev/null
+++ b/tools/testing/selftests/x86/vdso_restorer.c
@@ -0,0 +1,88 @@
1/*
2 * vdso_restorer.c - tests vDSO-based signal restore
3 * Copyright (c) 2015 Andrew Lutomirski
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it 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
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * This makes sure that sa_restorer == NULL keeps working on 32-bit
15 * configurations. Modern glibc doesn't use it under any circumstances,
16 * so it's easy to overlook breakage.
17 *
18 * 64-bit userspace has never supported sa_restorer == NULL, so this is
19 * 32-bit only.
20 */
21
22#define _GNU_SOURCE
23
24#include <err.h>
25#include <stdio.h>
26#include <string.h>
27#include <signal.h>
28#include <unistd.h>
29#include <syscall.h>
30#include <sys/syscall.h>
31
32/* Open-code this -- the headers are too messy to easily use them. */
33struct real_sigaction {
34 void *handler;
35 unsigned long flags;
36 void *restorer;
37 unsigned int mask[2];
38};
39
40static volatile sig_atomic_t handler_called;
41
42static void handler_with_siginfo(int sig, siginfo_t *info, void *ctx_void)
43{
44 handler_called = 1;
45}
46
47static void handler_without_siginfo(int sig)
48{
49 handler_called = 1;
50}
51
52int main()
53{
54 int nerrs = 0;
55 struct real_sigaction sa;
56
57 memset(&sa, 0, sizeof(sa));
58 sa.handler = handler_with_siginfo;
59 sa.flags = SA_SIGINFO;
60 sa.restorer = NULL; /* request kernel-provided restorer */
61
62 if (syscall(SYS_rt_sigaction, SIGUSR1, &sa, NULL, 8) != 0)
63 err(1, "raw rt_sigaction syscall");
64
65 raise(SIGUSR1);
66
67 if (handler_called) {
68 printf("[OK]\tSA_SIGINFO handler returned successfully\n");
69 } else {
70 printf("[FAIL]\tSA_SIGINFO handler was not called\n");
71 nerrs++;
72 }
73
74 sa.flags = 0;
75 sa.handler = handler_without_siginfo;
76 if (syscall(SYS_sigaction, SIGUSR1, &sa, 0) != 0)
77 err(1, "raw sigaction syscall");
78 handler_called = 0;
79
80 raise(SIGUSR1);
81
82 if (handler_called) {
83 printf("[OK]\t!SA_SIGINFO handler returned successfully\n");
84 } else {
85 printf("[FAIL]\t!SA_SIGINFO handler was not called\n");
86 nerrs++;
87 }
88}