]> git.karo-electronics.de Git - karo-tx-linux.git/blob - tools/perf/tests/bp_signal.c
Merge tag 'platform-drivers-x86-v4.12-2' of git://git.infradead.org/linux-platform...
[karo-tx-linux.git] / tools / perf / tests / bp_signal.c
1 /*
2  * Inspired by breakpoint overflow test done by
3  * Vince Weaver <vincent.weaver@maine.edu> for perf_event_tests
4  * (git://github.com/deater/perf_event_tests)
5  */
6
7 /*
8  * Powerpc needs __SANE_USERSPACE_TYPES__ before <linux/types.h> to select
9  * 'int-ll64.h' and avoid compile warnings when printing __u64 with %llu.
10  */
11 #define __SANE_USERSPACE_TYPES__
12
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <unistd.h>
16 #include <string.h>
17 #include <sys/ioctl.h>
18 #include <time.h>
19 #include <fcntl.h>
20 #include <signal.h>
21 #include <sys/mman.h>
22 #include <linux/compiler.h>
23 #include <linux/hw_breakpoint.h>
24
25 #include "tests.h"
26 #include "debug.h"
27 #include "perf.h"
28 #include "cloexec.h"
29
30 static int fd1;
31 static int fd2;
32 static int fd3;
33 static int overflows;
34 static int overflows_2;
35
36 volatile long the_var;
37
38
39 /*
40  * Use ASM to ensure watchpoint and breakpoint can be triggered
41  * at one instruction.
42  */
43 #if defined (__x86_64__)
44 extern void __test_function(volatile long *ptr);
45 asm (
46         ".globl __test_function\n"
47         "__test_function:\n"
48         "incq (%rdi)\n"
49         "ret\n");
50 #elif defined (__aarch64__)
51 extern void __test_function(volatile long *ptr);
52 asm (
53         ".globl __test_function\n"
54         "__test_function:\n"
55         "str x30, [x0]\n"
56         "ret\n");
57
58 #else
59 static void __test_function(volatile long *ptr)
60 {
61         *ptr = 0x1234;
62 }
63 #endif
64
65 __attribute__ ((noinline))
66 static int test_function(void)
67 {
68         __test_function(&the_var);
69         the_var++;
70         return time(NULL);
71 }
72
73 static void sig_handler_2(int signum __maybe_unused,
74                           siginfo_t *oh __maybe_unused,
75                           void *uc __maybe_unused)
76 {
77         overflows_2++;
78         if (overflows_2 > 10) {
79                 ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
80                 ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
81                 ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
82         }
83 }
84
85 static void sig_handler(int signum __maybe_unused,
86                         siginfo_t *oh __maybe_unused,
87                         void *uc __maybe_unused)
88 {
89         overflows++;
90
91         if (overflows > 10) {
92                 /*
93                  * This should be executed only once during
94                  * this test, if we are here for the 10th
95                  * time, consider this the recursive issue.
96                  *
97                  * We can get out of here by disable events,
98                  * so no new SIGIO is delivered.
99                  */
100                 ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
101                 ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
102                 ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
103         }
104 }
105
106 static int __event(bool is_x, void *addr, int sig)
107 {
108         struct perf_event_attr pe;
109         int fd;
110
111         memset(&pe, 0, sizeof(struct perf_event_attr));
112         pe.type = PERF_TYPE_BREAKPOINT;
113         pe.size = sizeof(struct perf_event_attr);
114
115         pe.config = 0;
116         pe.bp_type = is_x ? HW_BREAKPOINT_X : HW_BREAKPOINT_W;
117         pe.bp_addr = (unsigned long) addr;
118         pe.bp_len = sizeof(long);
119
120         pe.sample_period = 1;
121         pe.sample_type = PERF_SAMPLE_IP;
122         pe.wakeup_events = 1;
123
124         pe.disabled = 1;
125         pe.exclude_kernel = 1;
126         pe.exclude_hv = 1;
127
128         fd = sys_perf_event_open(&pe, 0, -1, -1,
129                                  perf_event_open_cloexec_flag());
130         if (fd < 0) {
131                 pr_debug("failed opening event %llx\n", pe.config);
132                 return TEST_FAIL;
133         }
134
135         fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC);
136         fcntl(fd, F_SETSIG, sig);
137         fcntl(fd, F_SETOWN, getpid());
138
139         ioctl(fd, PERF_EVENT_IOC_RESET, 0);
140
141         return fd;
142 }
143
144 static int bp_event(void *addr, int sig)
145 {
146         return __event(true, addr, sig);
147 }
148
149 static int wp_event(void *addr, int sig)
150 {
151         return __event(false, addr, sig);
152 }
153
154 static long long bp_count(int fd)
155 {
156         long long count;
157         int ret;
158
159         ret = read(fd, &count, sizeof(long long));
160         if (ret != sizeof(long long)) {
161                 pr_debug("failed to read: %d\n", ret);
162                 return TEST_FAIL;
163         }
164
165         return count;
166 }
167
168 int test__bp_signal(int subtest __maybe_unused)
169 {
170         struct sigaction sa;
171         long long count1, count2, count3;
172
173         /* setup SIGIO signal handler */
174         memset(&sa, 0, sizeof(struct sigaction));
175         sa.sa_sigaction = (void *) sig_handler;
176         sa.sa_flags = SA_SIGINFO;
177
178         if (sigaction(SIGIO, &sa, NULL) < 0) {
179                 pr_debug("failed setting up signal handler\n");
180                 return TEST_FAIL;
181         }
182
183         sa.sa_sigaction = (void *) sig_handler_2;
184         if (sigaction(SIGUSR1, &sa, NULL) < 0) {
185                 pr_debug("failed setting up signal handler 2\n");
186                 return TEST_FAIL;
187         }
188
189         /*
190          * We create following events:
191          *
192          * fd1 - breakpoint event on __test_function with SIGIO
193          *       signal configured. We should get signal
194          *       notification each time the breakpoint is hit
195          *
196          * fd2 - breakpoint event on sig_handler with SIGUSR1
197          *       configured. We should get SIGUSR1 each time when
198          *       breakpoint is hit
199          *
200          * fd3 - watchpoint event on __test_function with SIGIO
201          *       configured.
202          *
203          * Following processing should happen:
204          *   Exec:               Action:                       Result:
205          *   incq (%rdi)       - fd1 event breakpoint hit   -> count1 == 1
206          *                     - SIGIO is delivered
207          *   sig_handler       - fd2 event breakpoint hit   -> count2 == 1
208          *                     - SIGUSR1 is delivered
209          *   sig_handler_2                                  -> overflows_2 == 1  (nested signal)
210          *   sys_rt_sigreturn  - return from sig_handler_2
211          *   overflows++                                    -> overflows = 1
212          *   sys_rt_sigreturn  - return from sig_handler
213          *   incq (%rdi)       - fd3 event watchpoint hit   -> count3 == 1       (wp and bp in one insn)
214          *                     - SIGIO is delivered
215          *   sig_handler       - fd2 event breakpoint hit   -> count2 == 2
216          *                     - SIGUSR1 is delivered
217          *   sig_handler_2                                  -> overflows_2 == 2  (nested signal)
218          *   sys_rt_sigreturn  - return from sig_handler_2
219          *   overflows++                                    -> overflows = 2
220          *   sys_rt_sigreturn  - return from sig_handler
221          *   the_var++         - fd3 event watchpoint hit   -> count3 == 2       (standalone watchpoint)
222          *                     - SIGIO is delivered
223          *   sig_handler       - fd2 event breakpoint hit   -> count2 == 3
224          *                     - SIGUSR1 is delivered
225          *   sig_handler_2                                  -> overflows_2 == 3  (nested signal)
226          *   sys_rt_sigreturn  - return from sig_handler_2
227          *   overflows++                                    -> overflows == 3
228          *   sys_rt_sigreturn  - return from sig_handler
229          *
230          * The test case check following error conditions:
231          * - we get stuck in signal handler because of debug
232          *   exception being triggered receursively due to
233          *   the wrong RF EFLAG management
234          *
235          * - we never trigger the sig_handler breakpoint due
236          *   to the rong RF EFLAG management
237          *
238          */
239
240         fd1 = bp_event(__test_function, SIGIO);
241         fd2 = bp_event(sig_handler, SIGUSR1);
242         fd3 = wp_event((void *)&the_var, SIGIO);
243
244         ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0);
245         ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);
246         ioctl(fd3, PERF_EVENT_IOC_ENABLE, 0);
247
248         /*
249          * Kick off the test by trigering 'fd1'
250          * breakpoint.
251          */
252         test_function();
253
254         ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
255         ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
256         ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
257
258         count1 = bp_count(fd1);
259         count2 = bp_count(fd2);
260         count3 = bp_count(fd3);
261
262         close(fd1);
263         close(fd2);
264         close(fd3);
265
266         pr_debug("count1 %lld, count2 %lld, count3 %lld, overflow %d, overflows_2 %d\n",
267                  count1, count2, count3, overflows, overflows_2);
268
269         if (count1 != 1) {
270                 if (count1 == 11)
271                         pr_debug("failed: RF EFLAG recursion issue detected\n");
272                 else
273                         pr_debug("failed: wrong count for bp1%lld\n", count1);
274         }
275
276         if (overflows != 3)
277                 pr_debug("failed: wrong overflow hit\n");
278
279         if (overflows_2 != 3)
280                 pr_debug("failed: wrong overflow_2 hit\n");
281
282         if (count2 != 3)
283                 pr_debug("failed: wrong count for bp2\n");
284
285         if (count3 != 2)
286                 pr_debug("failed: wrong count for bp3\n");
287
288         return count1 == 1 && overflows == 3 && count2 == 3 && overflows_2 == 3 && count3 == 2 ?
289                 TEST_OK : TEST_FAIL;
290 }
291
292 bool test__bp_signal_is_supported(void)
293 {
294 /*
295  * The powerpc so far does not have support to even create
296  * instruction breakpoint using the perf event interface.
297  * Once it's there we can release this.
298  */
299 #ifdef __powerpc__
300         return false;
301 #else
302         return true;
303 #endif
304 }