bp_signal.c 7.7 KB
Newer Older
1 2 3 4 5 6
/*
 * Inspired by breakpoint overflow test done by
 * Vince Weaver <vincent.weaver@maine.edu> for perf_event_tests
 * (git://github.com/deater/perf_event_tests)
 */

7 8 9 10 11 12
/*
 * Powerpc needs __SANE_USERSPACE_TYPES__ before <linux/types.h> to select
 * 'int-ll64.h' and avoid compile warnings when printing __u64 with %llu.
 */
#define __SANE_USERSPACE_TYPES__

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <time.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/mman.h>
#include <linux/compiler.h>
#include <linux/hw_breakpoint.h>

#include "tests.h"
#include "debug.h"
#include "perf.h"
28
#include "cloexec.h"
29 30 31

static int fd1;
static int fd2;
W
Wang Nan 已提交
32
static int fd3;
33
static int overflows;
W
Wang Nan 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
static int overflows_2;

volatile long the_var;


/*
 * Use ASM to ensure watchpoint and breakpoint can be triggered
 * at one instruction.
 */
#if defined (__x86_64__)
extern void __test_function(volatile long *ptr);
asm (
	".globl __test_function\n"
	"__test_function:\n"
	"incq (%rdi)\n"
	"ret\n");
#elif defined (__aarch64__)
extern void __test_function(volatile long *ptr);
asm (
	".globl __test_function\n"
	"__test_function:\n"
	"str x30, [x0]\n"
	"ret\n");

#else
static void __test_function(volatile long *ptr)
{
	*ptr = 0x1234;
}
#endif
64 65 66 67

__attribute__ ((noinline))
static int test_function(void)
{
W
Wang Nan 已提交
68 69
	__test_function(&the_var);
	the_var++;
70 71 72
	return time(NULL);
}

W
Wang Nan 已提交
73 74 75 76 77 78 79 80 81 82 83 84
static void sig_handler_2(int signum __maybe_unused,
			  siginfo_t *oh __maybe_unused,
			  void *uc __maybe_unused)
{
	overflows_2++;
	if (overflows_2 > 10) {
		ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
		ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
		ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
	}
}

85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
static void sig_handler(int signum __maybe_unused,
			siginfo_t *oh __maybe_unused,
			void *uc __maybe_unused)
{
	overflows++;

	if (overflows > 10) {
		/*
		 * This should be executed only once during
		 * this test, if we are here for the 10th
		 * time, consider this the recursive issue.
		 *
		 * We can get out of here by disable events,
		 * so no new SIGIO is delivered.
		 */
		ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
		ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
W
Wang Nan 已提交
102
		ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
103 104 105
	}
}

106
static int __event(bool is_x, void *addr, int sig)
107 108 109 110 111 112 113 114 115
{
	struct perf_event_attr pe;
	int fd;

	memset(&pe, 0, sizeof(struct perf_event_attr));
	pe.type = PERF_TYPE_BREAKPOINT;
	pe.size = sizeof(struct perf_event_attr);

	pe.config = 0;
W
Wang Nan 已提交
116 117
	pe.bp_type = is_x ? HW_BREAKPOINT_X : HW_BREAKPOINT_W;
	pe.bp_addr = (unsigned long) addr;
118 119 120 121 122 123 124 125 126 127
	pe.bp_len = sizeof(long);

	pe.sample_period = 1;
	pe.sample_type = PERF_SAMPLE_IP;
	pe.wakeup_events = 1;

	pe.disabled = 1;
	pe.exclude_kernel = 1;
	pe.exclude_hv = 1;

128 129
	fd = sys_perf_event_open(&pe, 0, -1, -1,
				 perf_event_open_cloexec_flag());
130 131 132 133 134
	if (fd < 0) {
		pr_debug("failed opening event %llx\n", pe.config);
		return TEST_FAIL;
	}

W
Wang Nan 已提交
135
	fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC);
136
	fcntl(fd, F_SETSIG, sig);
W
Wang Nan 已提交
137
	fcntl(fd, F_SETOWN, getpid());
138 139 140 141 142 143

	ioctl(fd, PERF_EVENT_IOC_RESET, 0);

	return fd;
}

144
static int bp_event(void *addr, int sig)
W
Wang Nan 已提交
145
{
146
	return __event(true, addr, sig);
W
Wang Nan 已提交
147 148
}

149
static int wp_event(void *addr, int sig)
W
Wang Nan 已提交
150
{
151
	return __event(false, addr, sig);
W
Wang Nan 已提交
152 153
}

154 155 156 157 158 159 160 161 162 163 164 165 166 167
static long long bp_count(int fd)
{
	long long count;
	int ret;

	ret = read(fd, &count, sizeof(long long));
	if (ret != sizeof(long long)) {
		pr_debug("failed to read: %d\n", ret);
		return TEST_FAIL;
	}

	return count;
}

168
int test__bp_signal(int subtest __maybe_unused)
169 170
{
	struct sigaction sa;
W
Wang Nan 已提交
171
	long long count1, count2, count3;
172 173 174 175 176 177 178 179 180 181 182

	/* setup SIGIO signal handler */
	memset(&sa, 0, sizeof(struct sigaction));
	sa.sa_sigaction = (void *) sig_handler;
	sa.sa_flags = SA_SIGINFO;

	if (sigaction(SIGIO, &sa, NULL) < 0) {
		pr_debug("failed setting up signal handler\n");
		return TEST_FAIL;
	}

W
Wang Nan 已提交
183 184 185 186 187 188
	sa.sa_sigaction = (void *) sig_handler_2;
	if (sigaction(SIGUSR1, &sa, NULL) < 0) {
		pr_debug("failed setting up signal handler 2\n");
		return TEST_FAIL;
	}

189 190 191
	/*
	 * We create following events:
	 *
W
Wang Nan 已提交
192
	 * fd1 - breakpoint event on __test_function with SIGIO
193 194 195
	 *       signal configured. We should get signal
	 *       notification each time the breakpoint is hit
	 *
W
Wang Nan 已提交
196 197 198 199 200
	 * fd2 - breakpoint event on sig_handler with SIGUSR1
	 *       configured. We should get SIGUSR1 each time when
	 *       breakpoint is hit
	 *
	 * fd3 - watchpoint event on __test_function with SIGIO
201 202 203
	 *       configured.
	 *
	 * Following processing should happen:
W
Wang Nan 已提交
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
	 *   Exec:               Action:                       Result:
	 *   incq (%rdi)       - fd1 event breakpoint hit   -> count1 == 1
	 *                     - SIGIO is delivered
	 *   sig_handler       - fd2 event breakpoint hit   -> count2 == 1
	 *                     - SIGUSR1 is delivered
	 *   sig_handler_2                                  -> overflows_2 == 1  (nested signal)
	 *   sys_rt_sigreturn  - return from sig_handler_2
	 *   overflows++                                    -> overflows = 1
	 *   sys_rt_sigreturn  - return from sig_handler
	 *   incq (%rdi)       - fd3 event watchpoint hit   -> count3 == 1       (wp and bp in one insn)
	 *                     - SIGIO is delivered
	 *   sig_handler       - fd2 event breakpoint hit   -> count2 == 2
	 *                     - SIGUSR1 is delivered
	 *   sig_handler_2                                  -> overflows_2 == 2  (nested signal)
	 *   sys_rt_sigreturn  - return from sig_handler_2
	 *   overflows++                                    -> overflows = 2
	 *   sys_rt_sigreturn  - return from sig_handler
	 *   the_var++         - fd3 event watchpoint hit   -> count3 == 2       (standalone watchpoint)
	 *                     - SIGIO is delivered
	 *   sig_handler       - fd2 event breakpoint hit   -> count2 == 3
	 *                     - SIGUSR1 is delivered
	 *   sig_handler_2                                  -> overflows_2 == 3  (nested signal)
	 *   sys_rt_sigreturn  - return from sig_handler_2
	 *   overflows++                                    -> overflows == 3
	 *   sys_rt_sigreturn  - return from sig_handler
229 230 231 232 233 234 235 236 237 238 239
	 *
	 * The test case check following error conditions:
	 * - we get stuck in signal handler because of debug
	 *   exception being triggered receursively due to
	 *   the wrong RF EFLAG management
	 *
	 * - we never trigger the sig_handler breakpoint due
	 *   to the rong RF EFLAG management
	 *
	 */

W
Wang Nan 已提交
240 241 242
	fd1 = bp_event(__test_function, SIGIO);
	fd2 = bp_event(sig_handler, SIGUSR1);
	fd3 = wp_event((void *)&the_var, SIGIO);
243 244 245

	ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0);
	ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);
W
Wang Nan 已提交
246
	ioctl(fd3, PERF_EVENT_IOC_ENABLE, 0);
247 248 249 250 251 252 253 254 255

	/*
	 * Kick off the test by trigering 'fd1'
	 * breakpoint.
	 */
	test_function();

	ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
	ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
W
Wang Nan 已提交
256
	ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
257 258 259

	count1 = bp_count(fd1);
	count2 = bp_count(fd2);
W
Wang Nan 已提交
260
	count3 = bp_count(fd3);
261 262 263

	close(fd1);
	close(fd2);
W
Wang Nan 已提交
264
	close(fd3);
265

W
Wang Nan 已提交
266 267
	pr_debug("count1 %lld, count2 %lld, count3 %lld, overflow %d, overflows_2 %d\n",
		 count1, count2, count3, overflows, overflows_2);
268 269 270 271 272 273 274 275

	if (count1 != 1) {
		if (count1 == 11)
			pr_debug("failed: RF EFLAG recursion issue detected\n");
		else
			pr_debug("failed: wrong count for bp1%lld\n", count1);
	}

W
Wang Nan 已提交
276
	if (overflows != 3)
277 278
		pr_debug("failed: wrong overflow hit\n");

W
Wang Nan 已提交
279 280 281 282
	if (overflows_2 != 3)
		pr_debug("failed: wrong overflow_2 hit\n");

	if (count2 != 3)
283 284
		pr_debug("failed: wrong count for bp2\n");

W
Wang Nan 已提交
285 286 287 288
	if (count3 != 2)
		pr_debug("failed: wrong count for bp3\n");

	return count1 == 1 && overflows == 3 && count2 == 3 && overflows_2 == 3 && count3 == 2 ?
289 290
		TEST_OK : TEST_FAIL;
}
291 292 293 294 295 296 297 298 299 300 301 302 303 304

bool test__bp_signal_is_supported(void)
{
/*
 * The powerpc so far does not have support to even create
 * instruction breakpoint using the perf event interface.
 * Once it's there we can release this.
 */
#ifdef __powerpc__
	return false;
#else
	return true;
#endif
}