Skip to content

Commit 8fd34e1

Browse files
WangNan0acmel
authored andcommitted
perf test: Improve bp_signal
Will Deacon [1] has some question on patch [2]. This patch improves test__bp_signal so we can test: 1. A watchpoint and a breakpoint that fire on the same instruction 2. Nested signals Test result: On x86_64 and ARM64 (result are similar with patch [2] on ARM64): # ./perf test -v signal 17: Test breakpoint overflow signal handler : --- start --- test child forked, pid 10213 count1 1, count2 3, count3 2, overflow 3, overflows_2 3 test child finished with 0 ---- end ---- Test breakpoint overflow signal handler: Ok So at least 2 cases Will doubted are handled correctly. [1] http://lkml.kernel.org/g/20160104165535.GI1616@arm.com [2] http://lkml.kernel.org/g/1450921362-198371-1-git-send-email-wangnan0@huawei.com Signed-off-by: Wang Nan <wangnan0@huawei.com> Cc: Alexei Starovoitov <ast@kernel.org> Cc: Brendan Gregg <brendan.d.gregg@gmail.com> Cc: Daniel Borkmann <daniel@iogearbox.net> Cc: He Kuang <hekuang@huawei.com> Cc: Li Zefan <lizefan@huawei.com> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Will Deacon <will.deacon@arm.com> Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1453715801-7732-9-git-send-email-wangnan0@huawei.com Signed-off-by: Jiri Olsa <jolsa@kernel.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
1 parent 6a7d550 commit 8fd34e1

File tree

1 file changed

+118
-22
lines changed

1 file changed

+118
-22
lines changed

tools/perf/tests/bp_signal.c

+118-22
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,59 @@
2929

3030
static int fd1;
3131
static int fd2;
32+
static int fd3;
3233
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
3364

3465
__attribute__ ((noinline))
3566
static int test_function(void)
3667
{
68+
__test_function(&the_var);
69+
the_var++;
3770
return time(NULL);
3871
}
3972

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+
4085
static void sig_handler(int signum __maybe_unused,
4186
siginfo_t *oh __maybe_unused,
4287
void *uc __maybe_unused)
@@ -54,10 +99,11 @@ static void sig_handler(int signum __maybe_unused,
5499
*/
55100
ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
56101
ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
102+
ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
57103
}
58104
}
59105

60-
static int bp_event(void *fn, int setup_signal)
106+
static int __event(bool is_x, void *addr, int signal)
61107
{
62108
struct perf_event_attr pe;
63109
int fd;
@@ -67,8 +113,8 @@ static int bp_event(void *fn, int setup_signal)
67113
pe.size = sizeof(struct perf_event_attr);
68114

69115
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;
72118
pe.bp_len = sizeof(long);
73119

74120
pe.sample_period = 1;
@@ -86,17 +132,25 @@ static int bp_event(void *fn, int setup_signal)
86132
return TEST_FAIL;
87133
}
88134

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());
94138

95139
ioctl(fd, PERF_EVENT_IOC_RESET, 0);
96140

97141
return fd;
98142
}
99143

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+
100154
static long long bp_count(int fd)
101155
{
102156
long long count;
@@ -114,7 +168,7 @@ static long long bp_count(int fd)
114168
int test__bp_signal(int subtest __maybe_unused)
115169
{
116170
struct sigaction sa;
117-
long long count1, count2;
171+
long long count1, count2, count3;
118172

119173
/* setup SIGIO signal handler */
120174
memset(&sa, 0, sizeof(struct sigaction));
@@ -126,21 +180,52 @@ int test__bp_signal(int subtest __maybe_unused)
126180
return TEST_FAIL;
127181
}
128182

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+
129189
/*
130190
* We create following events:
131191
*
132-
* fd1 - breakpoint event on test_function with SIGIO
192+
* fd1 - breakpoint event on __test_function with SIGIO
133193
* signal configured. We should get signal
134194
* notification each time the breakpoint is hit
135195
*
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
137201
* configured.
138202
*
139203
* 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
144229
*
145230
* The test case check following error conditions:
146231
* - we get stuck in signal handler because of debug
@@ -152,11 +237,13 @@ int test__bp_signal(int subtest __maybe_unused)
152237
*
153238
*/
154239

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);
157243

158244
ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0);
159245
ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);
246+
ioctl(fd3, PERF_EVENT_IOC_ENABLE, 0);
160247

161248
/*
162249
* Kick off the test by trigering 'fd1'
@@ -166,15 +253,18 @@ int test__bp_signal(int subtest __maybe_unused)
166253

167254
ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
168255
ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
256+
ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
169257

170258
count1 = bp_count(fd1);
171259
count2 = bp_count(fd2);
260+
count3 = bp_count(fd3);
172261

173262
close(fd1);
174263
close(fd2);
264+
close(fd3);
175265

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);
178268

179269
if (count1 != 1) {
180270
if (count1 == 11)
@@ -183,12 +273,18 @@ int test__bp_signal(int subtest __maybe_unused)
183273
pr_debug("failed: wrong count for bp1%lld\n", count1);
184274
}
185275

186-
if (overflows != 1)
276+
if (overflows != 3)
187277
pr_debug("failed: wrong overflow hit\n");
188278

189-
if (count2 != 1)
279+
if (overflows_2 != 3)
280+
pr_debug("failed: wrong overflow_2 hit\n");
281+
282+
if (count2 != 3)
190283
pr_debug("failed: wrong count for bp2\n");
191284

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 ?
193289
TEST_OK : TEST_FAIL;
194290
}

0 commit comments

Comments
 (0)