aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/tests/bp_signal.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-04-30 10:41:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-04-30 10:41:01 -0400
commite0972916e8fe943f342b0dd1c9d43dbf5bc261c2 (patch)
tree690c436f1f9b839c4ba34d17ab3efa63b97a2dce /tools/perf/tests/bp_signal.c
parent1f889ec62c3f0d8913f3c32f9aff2a1e15099346 (diff)
parent5ac2b5c2721501a8f5c5e1cd4116cbc31ace6886 (diff)
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Ingo Molnar: "Features: - Add "uretprobes" - an optimization to uprobes, like kretprobes are an optimization to kprobes. "perf probe -x file sym%return" now works like kretprobes. By Oleg Nesterov. - Introduce per core aggregation in 'perf stat', from Stephane Eranian. - Add memory profiling via PEBS, from Stephane Eranian. - Event group view for 'annotate' in --stdio, --tui and --gtk, from Namhyung Kim. - Add support for AMD NB and L2I "uncore" counters, by Jacob Shin. - Add Ivy Bridge-EP uncore support, by Zheng Yan - IBM zEnterprise EC12 oprofile support patchlet from Robert Richter. - Add perf test entries for checking breakpoint overflow signal handler issues, from Jiri Olsa. - Add perf test entry for for checking number of EXIT events, from Namhyung Kim. - Add perf test entries for checking --cpu in record and stat, from Jiri Olsa. - Introduce perf stat --repeat forever, from Frederik Deweerdt. - Add --no-demangle to report/top, from Namhyung Kim. - PowerPC fixes plus a couple of cleanups/optimizations in uprobes and trace_uprobes, by Oleg Nesterov. Various fixes and refactorings: - Fix dependency of the python binding wrt libtraceevent, from Naohiro Aota. - Simplify some perf_evlist methods and to allow 'stat' to share code with 'record' and 'trace', by Arnaldo Carvalho de Melo. - Remove dead code in related to libtraceevent integration, from Namhyung Kim. - Revert "perf sched: Handle PERF_RECORD_EXIT events" to get 'perf sched lat' back working, by Arnaldo Carvalho de Melo - We don't use Newt anymore, just plain libslang, by Arnaldo Carvalho de Melo. - Kill a bunch of die() calls, from Namhyung Kim. - Fix build on non-glibc systems due to libio.h absence, from Cody P Schafer. - Remove some perf_session and tracing dead code, from David Ahern. - Honor parallel jobs, fix from Borislav Petkov - Introduce tools/lib/lk library, initially just removing duplication among tools/perf and tools/vm. from Borislav Petkov ... and many more I missed to list, see the shortlog and git log for more details." * 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (136 commits) perf/x86/intel/P4: Robistify P4 PMU types perf/x86/amd: Fix AMD NB and L2I "uncore" support perf/x86/amd: Remove old-style NB counter support from perf_event_amd.c perf/x86: Check all MSRs before passing hw check perf/x86/amd: Add support for AMD NB and L2I "uncore" counters perf/x86/intel: Add Ivy Bridge-EP uncore support perf/x86/intel: Fix SNB-EP CBO and PCU uncore PMU filter management perf/x86: Avoid kfree() in CPU_{STARTING,DYING} uprobes/perf: Avoid perf_trace_buf_prepare/submit if ->perf_events is empty uprobes/tracing: Don't pass addr=ip to perf_trace_buf_submit() uprobes/tracing: Change create_trace_uprobe() to support uretprobes uprobes/tracing: Make seq_printf() code uretprobe-friendly uprobes/tracing: Make register_uprobe_event() paths uretprobe-friendly uprobes/tracing: Make uprobe_{trace,perf}_print() uretprobe-friendly uprobes/tracing: Introduce is_ret_probe() and uretprobe_dispatcher() uprobes/tracing: Introduce uprobe_{trace,perf}_print() helpers uprobes/tracing: Generalize struct uprobe_trace_entry_head uprobes/tracing: Kill the pointless local_save_flags/preempt_count calls uprobes/tracing: Kill the pointless seq_print_ip_sym() call uprobes/tracing: Kill the pointless task_pt_regs() calls ...
Diffstat (limited to 'tools/perf/tests/bp_signal.c')
-rw-r--r--tools/perf/tests/bp_signal.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/tools/perf/tests/bp_signal.c b/tools/perf/tests/bp_signal.c
new file mode 100644
index 000000000000..68daa289e94c
--- /dev/null
+++ b/tools/perf/tests/bp_signal.c
@@ -0,0 +1,186 @@
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#include <stdlib.h>
8#include <stdio.h>
9#include <unistd.h>
10#include <string.h>
11#include <sys/ioctl.h>
12#include <time.h>
13#include <fcntl.h>
14#include <signal.h>
15#include <sys/mman.h>
16#include <linux/compiler.h>
17#include <linux/hw_breakpoint.h>
18
19#include "tests.h"
20#include "debug.h"
21#include "perf.h"
22
23static int fd1;
24static int fd2;
25static int overflows;
26
27__attribute__ ((noinline))
28static int test_function(void)
29{
30 return time(NULL);
31}
32
33static void sig_handler(int signum __maybe_unused,
34 siginfo_t *oh __maybe_unused,
35 void *uc __maybe_unused)
36{
37 overflows++;
38
39 if (overflows > 10) {
40 /*
41 * This should be executed only once during
42 * this test, if we are here for the 10th
43 * time, consider this the recursive issue.
44 *
45 * We can get out of here by disable events,
46 * so no new SIGIO is delivered.
47 */
48 ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
49 ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
50 }
51}
52
53static int bp_event(void *fn, int setup_signal)
54{
55 struct perf_event_attr pe;
56 int fd;
57
58 memset(&pe, 0, sizeof(struct perf_event_attr));
59 pe.type = PERF_TYPE_BREAKPOINT;
60 pe.size = sizeof(struct perf_event_attr);
61
62 pe.config = 0;
63 pe.bp_type = HW_BREAKPOINT_X;
64 pe.bp_addr = (unsigned long) fn;
65 pe.bp_len = sizeof(long);
66
67 pe.sample_period = 1;
68 pe.sample_type = PERF_SAMPLE_IP;
69 pe.wakeup_events = 1;
70
71 pe.disabled = 1;
72 pe.exclude_kernel = 1;
73 pe.exclude_hv = 1;
74
75 fd = sys_perf_event_open(&pe, 0, -1, -1, 0);
76 if (fd < 0) {
77 pr_debug("failed opening event %llx\n", pe.config);
78 return TEST_FAIL;
79 }
80
81 if (setup_signal) {
82 fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC);
83 fcntl(fd, F_SETSIG, SIGIO);
84 fcntl(fd, F_SETOWN, getpid());
85 }
86
87 ioctl(fd, PERF_EVENT_IOC_RESET, 0);
88
89 return fd;
90}
91
92static long long bp_count(int fd)
93{
94 long long count;
95 int ret;
96
97 ret = read(fd, &count, sizeof(long long));
98 if (ret != sizeof(long long)) {
99 pr_debug("failed to read: %d\n", ret);
100 return TEST_FAIL;
101 }
102
103 return count;
104}
105
106int test__bp_signal(void)
107{
108 struct sigaction sa;
109 long long count1, count2;
110
111 /* setup SIGIO signal handler */
112 memset(&sa, 0, sizeof(struct sigaction));
113 sa.sa_sigaction = (void *) sig_handler;
114 sa.sa_flags = SA_SIGINFO;
115
116 if (sigaction(SIGIO, &sa, NULL) < 0) {
117 pr_debug("failed setting up signal handler\n");
118 return TEST_FAIL;
119 }
120
121 /*
122 * We create following events:
123 *
124 * fd1 - breakpoint event on test_function with SIGIO
125 * signal configured. We should get signal
126 * notification each time the breakpoint is hit
127 *
128 * fd2 - breakpoint event on sig_handler without SIGIO
129 * configured.
130 *
131 * Following processing should happen:
132 * - execute test_function
133 * - fd1 event breakpoint hit -> count1 == 1
134 * - SIGIO is delivered -> overflows == 1
135 * - fd2 event breakpoint hit -> count2 == 1
136 *
137 * The test case check following error conditions:
138 * - we get stuck in signal handler because of debug
139 * exception being triggered receursively due to
140 * the wrong RF EFLAG management
141 *
142 * - we never trigger the sig_handler breakpoint due
143 * to the rong RF EFLAG management
144 *
145 */
146
147 fd1 = bp_event(test_function, 1);
148 fd2 = bp_event(sig_handler, 0);
149
150 ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0);
151 ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);
152
153 /*
154 * Kick off the test by trigering 'fd1'
155 * breakpoint.
156 */
157 test_function();
158
159 ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
160 ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
161
162 count1 = bp_count(fd1);
163 count2 = bp_count(fd2);
164
165 close(fd1);
166 close(fd2);
167
168 pr_debug("count1 %lld, count2 %lld, overflow %d\n",
169 count1, count2, overflows);
170
171 if (count1 != 1) {
172 if (count1 == 11)
173 pr_debug("failed: RF EFLAG recursion issue detected\n");
174 else
175 pr_debug("failed: wrong count for bp1%lld\n", count1);
176 }
177
178 if (overflows != 1)
179 pr_debug("failed: wrong overflow hit\n");
180
181 if (count2 != 1)
182 pr_debug("failed: wrong count for bp2\n");
183
184 return count1 == 1 && overflows == 1 && count2 == 1 ?
185 TEST_OK : TEST_FAIL;
186}