29
29
30
30
static int fd1 ;
31
31
static int fd2 ;
32
+ static int fd3 ;
32
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
33
64
34
65
__attribute__ ((noinline ))
35
66
static int test_function (void )
36
67
{
68
+ __test_function (& the_var );
69
+ the_var ++ ;
37
70
return time (NULL );
38
71
}
39
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
+
40
85
static void sig_handler (int signum __maybe_unused ,
41
86
siginfo_t * oh __maybe_unused ,
42
87
void * uc __maybe_unused )
@@ -54,10 +99,11 @@ static void sig_handler(int signum __maybe_unused,
54
99
*/
55
100
ioctl (fd1 , PERF_EVENT_IOC_DISABLE , 0 );
56
101
ioctl (fd2 , PERF_EVENT_IOC_DISABLE , 0 );
102
+ ioctl (fd3 , PERF_EVENT_IOC_DISABLE , 0 );
57
103
}
58
104
}
59
105
60
- static int bp_event ( void * fn , int setup_signal )
106
+ static int __event ( bool is_x , void * addr , int signal )
61
107
{
62
108
struct perf_event_attr pe ;
63
109
int fd ;
@@ -67,8 +113,8 @@ static int bp_event(void *fn, int setup_signal)
67
113
pe .size = sizeof (struct perf_event_attr );
68
114
69
115
pe .config = 0 ;
70
- pe .bp_type = HW_BREAKPOINT_X ;
71
- pe .bp_addr = (unsigned long ) fn ;
116
+ pe .bp_type = is_x ? HW_BREAKPOINT_X : HW_BREAKPOINT_W ;
117
+ pe .bp_addr = (unsigned long ) addr ;
72
118
pe .bp_len = sizeof (long );
73
119
74
120
pe .sample_period = 1 ;
@@ -86,17 +132,25 @@ static int bp_event(void *fn, int setup_signal)
86
132
return TEST_FAIL ;
87
133
}
88
134
89
- if (setup_signal ) {
90
- fcntl (fd , F_SETFL , O_RDWR |O_NONBLOCK |O_ASYNC );
91
- fcntl (fd , F_SETSIG , SIGIO );
92
- fcntl (fd , F_SETOWN , getpid ());
93
- }
135
+ fcntl (fd , F_SETFL , O_RDWR |O_NONBLOCK |O_ASYNC );
136
+ fcntl (fd , F_SETSIG , signal );
137
+ fcntl (fd , F_SETOWN , getpid ());
94
138
95
139
ioctl (fd , PERF_EVENT_IOC_RESET , 0 );
96
140
97
141
return fd ;
98
142
}
99
143
144
+ static int bp_event (void * addr , int signal )
145
+ {
146
+ return __event (true, addr , signal );
147
+ }
148
+
149
+ static int wp_event (void * addr , int signal )
150
+ {
151
+ return __event (false, addr , signal );
152
+ }
153
+
100
154
static long long bp_count (int fd )
101
155
{
102
156
long long count ;
@@ -114,7 +168,7 @@ static long long bp_count(int fd)
114
168
int test__bp_signal (int subtest __maybe_unused )
115
169
{
116
170
struct sigaction sa ;
117
- long long count1 , count2 ;
171
+ long long count1 , count2 , count3 ;
118
172
119
173
/* setup SIGIO signal handler */
120
174
memset (& sa , 0 , sizeof (struct sigaction ));
@@ -126,21 +180,52 @@ int test__bp_signal(int subtest __maybe_unused)
126
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
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
193
* signal configured. We should get signal
134
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
201
* configured.
138
202
*
139
203
* Following processing should happen:
140
- * - execute test_function
141
- * - fd1 event breakpoint hit -> count1 == 1
142
- * - SIGIO is delivered -> overflows == 1
143
- * - fd2 event breakpoint hit -> count2 == 1
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
144
229
*
145
230
* The test case check following error conditions:
146
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 );
156
- fd2 = bp_event (sig_handler , 0 );
240
+ fd1 = bp_event (__test_function , SIGIO );
241
+ fd2 = bp_event (sig_handler , SIGUSR1 );
242
+ fd3 = wp_event ((void * )& the_var , SIGIO );
157
243
158
244
ioctl (fd1 , PERF_EVENT_IOC_ENABLE , 0 );
159
245
ioctl (fd2 , PERF_EVENT_IOC_ENABLE , 0 );
246
+ ioctl (fd3 , PERF_EVENT_IOC_ENABLE , 0 );
160
247
161
248
/*
162
249
* Kick off the test by trigering 'fd1'
@@ -166,15 +253,18 @@ int test__bp_signal(int subtest __maybe_unused)
166
253
167
254
ioctl (fd1 , PERF_EVENT_IOC_DISABLE , 0 );
168
255
ioctl (fd2 , PERF_EVENT_IOC_DISABLE , 0 );
256
+ ioctl (fd3 , PERF_EVENT_IOC_DISABLE , 0 );
169
257
170
258
count1 = bp_count (fd1 );
171
259
count2 = bp_count (fd2 );
260
+ count3 = bp_count (fd3 );
172
261
173
262
close (fd1 );
174
263
close (fd2 );
264
+ close (fd3 );
175
265
176
- pr_debug ("count1 %lld, count2 %lld, overflow %d\n" ,
177
- count1 , count2 , overflows );
266
+ pr_debug ("count1 %lld, count2 %lld, count3 %lld, overflow %d, overflows_2 %d\n" ,
267
+ count1 , count2 , count3 , overflows , overflows_2 );
178
268
179
269
if (count1 != 1 ) {
180
270
if (count1 == 11 )
@@ -183,12 +273,18 @@ int test__bp_signal(int subtest __maybe_unused)
183
273
pr_debug ("failed: wrong count for bp1%lld\n" , count1 );
184
274
}
185
275
186
- if (overflows != 1 )
276
+ if (overflows != 3 )
187
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
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
289
TEST_OK : TEST_FAIL ;
194
290
}
0 commit comments