aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/tests/bp_signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/tests/bp_signal.c')
-rw-r--r--tools/perf/tests/bp_signal.c140
1 files changed, 118 insertions, 22 deletions
diff --git a/tools/perf/tests/bp_signal.c b/tools/perf/tests/bp_signal.c
index fb80c9eb6a95..e7664fe3bd33 100644
--- a/tools/perf/tests/bp_signal.c
+++ b/tools/perf/tests/bp_signal.c
@@ -29,14 +29,59 @@
29 29
30static int fd1; 30static int fd1;
31static int fd2; 31static int fd2;
32static int fd3;
32static int overflows; 33static int overflows;
34static int overflows_2;
35
36volatile 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__)
44extern void __test_function(volatile long *ptr);
45asm (
46 ".globl __test_function\n"
47 "__test_function:\n"
48 "incq (%rdi)\n"
49 "ret\n");
50#elif defined (__aarch64__)
51extern void __test_function(volatile long *ptr);
52asm (
53 ".globl __test_function\n"
54 "__test_function:\n"
55 "str x30, [x0]\n"
56 "ret\n");
57
58#else
59static void __test_function(volatile long *ptr)
60{
61 *ptr = 0x1234;
62}
63#endif
33 64
34__attribute__ ((noinline)) 65__attribute__ ((noinline))
35static int test_function(void) 66static int test_function(void)
36{ 67{
68 __test_function(&the_var);
69 the_var++;
37 return time(NULL); 70 return time(NULL);
38} 71}
39 72
73static 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
40static void sig_handler(int signum __maybe_unused, 85static void sig_handler(int signum __maybe_unused,
41 siginfo_t *oh __maybe_unused, 86 siginfo_t *oh __maybe_unused,
42 void *uc __maybe_unused) 87 void *uc __maybe_unused)
@@ -54,10 +99,11 @@ static void sig_handler(int signum __maybe_unused,
54 */ 99 */
55 ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0); 100 ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
56 ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0); 101 ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
102 ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
57 } 103 }
58} 104}
59 105
60static int bp_event(void *fn, int setup_signal) 106static int __event(bool is_x, void *addr, int sig)
61{ 107{
62 struct perf_event_attr pe; 108 struct perf_event_attr pe;
63 int fd; 109 int fd;
@@ -67,8 +113,8 @@ static int bp_event(void *fn, int setup_signal)
67 pe.size = sizeof(struct perf_event_attr); 113 pe.size = sizeof(struct perf_event_attr);
68 114
69 pe.config = 0; 115 pe.config = 0;
70 pe.bp_type = HW_BREAKPOINT_X; 116 pe.bp_type = is_x ? HW_BREAKPOINT_X : HW_BREAKPOINT_W;
71 pe.bp_addr = (unsigned long) fn; 117 pe.bp_addr = (unsigned long) addr;
72 pe.bp_len = sizeof(long); 118 pe.bp_len = sizeof(long);
73 119
74 pe.sample_period = 1; 120 pe.sample_period = 1;
@@ -86,17 +132,25 @@ static int bp_event(void *fn, int setup_signal)
86 return TEST_FAIL; 132 return TEST_FAIL;
87 } 133 }
88 134
89 if (setup_signal) { 135 fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC);
90 fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); 136 fcntl(fd, F_SETSIG, sig);
91 fcntl(fd, F_SETSIG, SIGIO); 137 fcntl(fd, F_SETOWN, getpid());
92 fcntl(fd, F_SETOWN, getpid());
93 }
94 138
95 ioctl(fd, PERF_EVENT_IOC_RESET, 0); 139 ioctl(fd, PERF_EVENT_IOC_RESET, 0);
96 140
97 return fd; 141 return fd;
98} 142}
99 143
144static int bp_event(void *addr, int sig)
145{
146 return __event(true, addr, sig);
147}
148
149static int wp_event(void *addr, int sig)
150{
151 return __event(false, addr, sig);
152}
153
100static long long bp_count(int fd) 154static long long bp_count(int fd)
101{ 155{
102 long long count; 156 long long count;
@@ -114,7 +168,7 @@ static long long bp_count(int fd)
114int test__bp_signal(int subtest __maybe_unused) 168int test__bp_signal(int subtest __maybe_unused)
115{ 169{
116 struct sigaction sa; 170 struct sigaction sa;
117 long long count1, count2; 171 long long count1, count2, count3;
118 172
119 /* setup SIGIO signal handler */ 173 /* setup SIGIO signal handler */
120 memset(&sa, 0, sizeof(struct sigaction)); 174 memset(&sa, 0, sizeof(struct sigaction));
@@ -126,21 +180,52 @@ int test__bp_signal(int subtest __maybe_unused)
126 return TEST_FAIL; 180 return TEST_FAIL;
127 } 181 }
128 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
129 /* 189 /*
130 * We create following events: 190 * We create following events:
131 * 191 *
132 * fd1 - breakpoint event on test_function with SIGIO 192 * fd1 - breakpoint event on __test_function with SIGIO
133 * signal configured. We should get signal 193 * signal configured. We should get signal
134 * notification each time the breakpoint is hit 194 * notification each time the breakpoint is hit
135 * 195 *
136 * fd2 - breakpoint event on sig_handler without SIGIO 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
137 * configured. 201 * configured.
138 * 202 *
139 * Following processing should happen: 203 * Following processing should happen:
140 * - execute test_function 204 * Exec: Action: Result:
141 * - fd1 event breakpoint hit -> count1 == 1 205 * incq (%rdi) - fd1 event breakpoint hit -> count1 == 1
142 * - SIGIO is delivered -> overflows == 1 206 * - SIGIO is delivered
143 * - fd2 event breakpoint hit -> count2 == 1 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
144 * 229 *
145 * The test case check following error conditions: 230 * The test case check following error conditions:
146 * - we get stuck in signal handler because of debug 231 * - we get stuck in signal handler because of debug
@@ -152,11 +237,13 @@ int test__bp_signal(int subtest __maybe_unused)
152 * 237 *
153 */ 238 */
154 239
155 fd1 = bp_event(test_function, 1); 240 fd1 = bp_event(__test_function, SIGIO);
156 fd2 = bp_event(sig_handler, 0); 241 fd2 = bp_event(sig_handler, SIGUSR1);
242 fd3 = wp_event((void *)&the_var, SIGIO);
157 243
158 ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0); 244 ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0);
159 ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0); 245 ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);
246 ioctl(fd3, PERF_EVENT_IOC_ENABLE, 0);
160 247
161 /* 248 /*
162 * Kick off the test by trigering 'fd1' 249 * Kick off the test by trigering 'fd1'
@@ -166,15 +253,18 @@ int test__bp_signal(int subtest __maybe_unused)
166 253
167 ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0); 254 ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
168 ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0); 255 ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
256 ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
169 257
170 count1 = bp_count(fd1); 258 count1 = bp_count(fd1);
171 count2 = bp_count(fd2); 259 count2 = bp_count(fd2);
260 count3 = bp_count(fd3);
172 261
173 close(fd1); 262 close(fd1);
174 close(fd2); 263 close(fd2);
264 close(fd3);
175 265
176 pr_debug("count1 %lld, count2 %lld, overflow %d\n", 266 pr_debug("count1 %lld, count2 %lld, count3 %lld, overflow %d, overflows_2 %d\n",
177 count1, count2, overflows); 267 count1, count2, count3, overflows, overflows_2);
178 268
179 if (count1 != 1) { 269 if (count1 != 1) {
180 if (count1 == 11) 270 if (count1 == 11)
@@ -183,12 +273,18 @@ int test__bp_signal(int subtest __maybe_unused)
183 pr_debug("failed: wrong count for bp1%lld\n", count1); 273 pr_debug("failed: wrong count for bp1%lld\n", count1);
184 } 274 }
185 275
186 if (overflows != 1) 276 if (overflows != 3)
187 pr_debug("failed: wrong overflow hit\n"); 277 pr_debug("failed: wrong overflow hit\n");
188 278
189 if (count2 != 1) 279 if (overflows_2 != 3)
280 pr_debug("failed: wrong overflow_2 hit\n");
281
282 if (count2 != 3)
190 pr_debug("failed: wrong count for bp2\n"); 283 pr_debug("failed: wrong count for bp2\n");
191 284
192 return count1 == 1 && overflows == 1 && count2 == 1 ? 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 ?
193 TEST_OK : TEST_FAIL; 289 TEST_OK : TEST_FAIL;
194} 290}