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