1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * perf events self profiling example test case for hw breakpoints.
4  *
5  * This tests perf PERF_TYPE_BREAKPOINT parameters
6  * 1) tests all variants of the break on read/write flags
7  * 2) tests exclude_user == 0 and 1
8  * 3) test array matches (if DAWR is supported))
9  * 4) test different numbers of breakpoints matches
10  *
11  * Configure this breakpoint, then read and write the data a number of
12  * times. Then check the output count from perf is as expected.
13  *
14  * Based on:
15  *   http://ozlabs.org/~anton/junkcode/perf_events_example1.c
16  *
17  * Copyright (C) 2018 Michael Neuling, IBM Corporation.
18  */
19 
20 #include <unistd.h>
21 #include <assert.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <signal.h>
25 #include <string.h>
26 #include <sys/ioctl.h>
27 #include <sys/wait.h>
28 #include <sys/ptrace.h>
29 #include <sys/sysinfo.h>
30 #include <asm/ptrace.h>
31 #include <elf.h>
32 #include <pthread.h>
33 #include <sys/syscall.h>
34 #include <linux/perf_event.h>
35 #include <linux/hw_breakpoint.h>
36 #include "utils.h"
37 
38 #ifndef PPC_DEBUG_FEATURE_DATA_BP_ARCH_31
39 #define PPC_DEBUG_FEATURE_DATA_BP_ARCH_31	0x20
40 #endif
41 
42 #define MAX_LOOPS 10000
43 
44 #define DAWR_LENGTH_MAX ((0x3f + 1) * 8)
45 
46 int nprocs;
47 
48 static volatile int a = 10;
49 static volatile int b = 10;
50 static volatile char c[512 + 8] __attribute__((aligned(512)));
51 
perf_event_attr_set(struct perf_event_attr * attr,__u32 type,__u64 addr,__u64 len,bool exclude_user)52 static void perf_event_attr_set(struct perf_event_attr *attr,
53 				__u32 type, __u64 addr, __u64 len,
54 				bool exclude_user)
55 {
56 	memset(attr, 0, sizeof(struct perf_event_attr));
57 	attr->type           = PERF_TYPE_BREAKPOINT;
58 	attr->size           = sizeof(struct perf_event_attr);
59 	attr->bp_type        = type;
60 	attr->bp_addr        = addr;
61 	attr->bp_len         = len;
62 	attr->exclude_kernel = 1;
63 	attr->exclude_hv     = 1;
64 	attr->exclude_guest  = 1;
65 	attr->exclude_user   = exclude_user;
66 	attr->disabled       = 1;
67 }
68 
69 static int
perf_process_event_open_exclude_user(__u32 type,__u64 addr,__u64 len,bool exclude_user)70 perf_process_event_open_exclude_user(__u32 type, __u64 addr, __u64 len, bool exclude_user)
71 {
72 	struct perf_event_attr attr;
73 
74 	perf_event_attr_set(&attr, type, addr, len, exclude_user);
75 	return syscall(__NR_perf_event_open, &attr, getpid(), -1, -1, 0);
76 }
77 
perf_process_event_open(__u32 type,__u64 addr,__u64 len)78 static int perf_process_event_open(__u32 type, __u64 addr, __u64 len)
79 {
80 	struct perf_event_attr attr;
81 
82 	perf_event_attr_set(&attr, type, addr, len, 0);
83 	return syscall(__NR_perf_event_open, &attr, getpid(), -1, -1, 0);
84 }
85 
perf_cpu_event_open(long cpu,__u32 type,__u64 addr,__u64 len)86 static int perf_cpu_event_open(long cpu, __u32 type, __u64 addr, __u64 len)
87 {
88 	struct perf_event_attr attr;
89 
90 	perf_event_attr_set(&attr, type, addr, len, 0);
91 	return syscall(__NR_perf_event_open, &attr, -1, cpu, -1, 0);
92 }
93 
close_fds(int * fd,int n)94 static void close_fds(int *fd, int n)
95 {
96 	int i;
97 
98 	for (i = 0; i < n; i++)
99 		close(fd[i]);
100 }
101 
read_fds(int * fd,int n)102 static unsigned long read_fds(int *fd, int n)
103 {
104 	int i;
105 	unsigned long c = 0;
106 	unsigned long count = 0;
107 	size_t res;
108 
109 	for (i = 0; i < n; i++) {
110 		res = read(fd[i], &c, sizeof(c));
111 		assert(res == sizeof(unsigned long long));
112 		count += c;
113 	}
114 	return count;
115 }
116 
reset_fds(int * fd,int n)117 static void reset_fds(int *fd, int n)
118 {
119 	int i;
120 
121 	for (i = 0; i < n; i++)
122 		ioctl(fd[i], PERF_EVENT_IOC_RESET);
123 }
124 
enable_fds(int * fd,int n)125 static void enable_fds(int *fd, int n)
126 {
127 	int i;
128 
129 	for (i = 0; i < n; i++)
130 		ioctl(fd[i], PERF_EVENT_IOC_ENABLE);
131 }
132 
disable_fds(int * fd,int n)133 static void disable_fds(int *fd, int n)
134 {
135 	int i;
136 
137 	for (i = 0; i < n; i++)
138 		ioctl(fd[i], PERF_EVENT_IOC_DISABLE);
139 }
140 
perf_systemwide_event_open(int * fd,__u32 type,__u64 addr,__u64 len)141 static int perf_systemwide_event_open(int *fd, __u32 type, __u64 addr, __u64 len)
142 {
143 	int i = 0;
144 
145 	/* Assume online processors are 0 to nprocs for simplisity */
146 	for (i = 0; i < nprocs; i++) {
147 		fd[i] = perf_cpu_event_open(i, type, addr, len);
148 		if (fd[i] < 0) {
149 			close_fds(fd, i);
150 			return fd[i];
151 		}
152 	}
153 	return 0;
154 }
155 
breakpoint_test(int len)156 static inline bool breakpoint_test(int len)
157 {
158 	int fd;
159 
160 	/* bp_addr can point anywhere but needs to be aligned */
161 	fd = perf_process_event_open(HW_BREAKPOINT_R, (__u64)(&fd) & 0xfffffffffffff800, len);
162 	if (fd < 0)
163 		return false;
164 	close(fd);
165 	return true;
166 }
167 
perf_breakpoint_supported(void)168 static inline bool perf_breakpoint_supported(void)
169 {
170 	return breakpoint_test(4);
171 }
172 
dawr_supported(void)173 static inline bool dawr_supported(void)
174 {
175 	return breakpoint_test(DAWR_LENGTH_MAX);
176 }
177 
runtestsingle(int readwriteflag,int exclude_user,int arraytest)178 static int runtestsingle(int readwriteflag, int exclude_user, int arraytest)
179 {
180 	int i,j;
181 	size_t res;
182 	unsigned long long breaks, needed;
183 	int readint;
184 	int readintarraybig[2*DAWR_LENGTH_MAX/sizeof(int)];
185 	int *readintalign;
186 	volatile int *ptr;
187 	int break_fd;
188 	int loop_num = MAX_LOOPS - (rand() % 100); /* provide some variability */
189 	volatile int *k;
190 	__u64 len;
191 
192 	/* align to 0x400 boundary as required by DAWR */
193 	readintalign = (int *)(((unsigned long)readintarraybig + 0x7ff) &
194 			       0xfffffffffffff800);
195 
196 	ptr = &readint;
197 	if (arraytest)
198 		ptr = &readintalign[0];
199 
200 	len = arraytest ? DAWR_LENGTH_MAX : sizeof(int);
201 	break_fd = perf_process_event_open_exclude_user(readwriteflag, (__u64)ptr,
202 							len, exclude_user);
203 	if (break_fd < 0) {
204 		perror("perf_process_event_open_exclude_user");
205 		exit(1);
206 	}
207 
208 	/* start counters */
209 	ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
210 
211 	/* Test a bunch of reads and writes */
212 	k = &readint;
213 	for (i = 0; i < loop_num; i++) {
214 		if (arraytest)
215 			k = &(readintalign[i % (DAWR_LENGTH_MAX/sizeof(int))]);
216 
217 		j = *k;
218 		*k = j;
219 	}
220 
221 	/* stop counters */
222 	ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
223 
224 	/* read and check counters */
225 	res = read(break_fd, &breaks, sizeof(unsigned long long));
226 	assert(res == sizeof(unsigned long long));
227 	/* we read and write each loop, so subtract the ones we are counting */
228 	needed = 0;
229 	if (readwriteflag & HW_BREAKPOINT_R)
230 		needed += loop_num;
231 	if (readwriteflag & HW_BREAKPOINT_W)
232 		needed += loop_num;
233 	needed = needed * (1 - exclude_user);
234 	printf("TESTED: addr:0x%lx brks:% 8lld loops:% 8i rw:%i !user:%i array:%i\n",
235 	       (unsigned long int)ptr, breaks, loop_num, readwriteflag, exclude_user, arraytest);
236 	if (breaks != needed) {
237 		printf("FAILED: 0x%lx brks:%lld needed:%lli %i %i %i\n\n",
238 		       (unsigned long int)ptr, breaks, needed, loop_num, readwriteflag, exclude_user);
239 		return 1;
240 	}
241 	close(break_fd);
242 
243 	return 0;
244 }
245 
runtest_dar_outside(void)246 static int runtest_dar_outside(void)
247 {
248 	void *target;
249 	volatile __u16 temp16;
250 	volatile __u64 temp64;
251 	int break_fd;
252 	unsigned long long breaks;
253 	int fail = 0;
254 	size_t res;
255 
256 	target = malloc(8);
257 	if (!target) {
258 		perror("malloc failed");
259 		exit(EXIT_FAILURE);
260 	}
261 
262 	/* watch middle half of target array */
263 	break_fd = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)(target + 2), 4);
264 	if (break_fd < 0) {
265 		free(target);
266 		perror("perf_process_event_open");
267 		exit(EXIT_FAILURE);
268 	}
269 
270 	/* Shouldn't hit. */
271 	ioctl(break_fd, PERF_EVENT_IOC_RESET);
272 	ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
273 	temp16 = *((__u16 *)target);
274 	*((__u16 *)target) = temp16;
275 	ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
276 	res = read(break_fd, &breaks, sizeof(unsigned long long));
277 	assert(res == sizeof(unsigned long long));
278 	if (breaks == 0) {
279 		printf("TESTED: No overlap\n");
280 	} else {
281 		printf("FAILED: No overlap: %lld != 0\n", breaks);
282 		fail = 1;
283 	}
284 
285 	/* Hit */
286 	ioctl(break_fd, PERF_EVENT_IOC_RESET);
287 	ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
288 	temp16 = *((__u16 *)(target + 1));
289 	*((__u16 *)(target + 1)) = temp16;
290 	ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
291 	res = read(break_fd, &breaks, sizeof(unsigned long long));
292 	assert(res == sizeof(unsigned long long));
293 	if (breaks == 2) {
294 		printf("TESTED: Partial overlap\n");
295 	} else {
296 		printf("FAILED: Partial overlap: %lld != 2\n", breaks);
297 		fail = 1;
298 	}
299 
300 	/* Hit */
301 	ioctl(break_fd, PERF_EVENT_IOC_RESET);
302 	ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
303 	temp16 = *((__u16 *)(target + 5));
304 	*((__u16 *)(target + 5)) = temp16;
305 	ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
306 	res = read(break_fd, &breaks, sizeof(unsigned long long));
307 	assert(res == sizeof(unsigned long long));
308 	if (breaks == 2) {
309 		printf("TESTED: Partial overlap\n");
310 	} else {
311 		printf("FAILED: Partial overlap: %lld != 2\n", breaks);
312 		fail = 1;
313 	}
314 
315 	/* Shouldn't Hit */
316 	ioctl(break_fd, PERF_EVENT_IOC_RESET);
317 	ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
318 	temp16 = *((__u16 *)(target + 6));
319 	*((__u16 *)(target + 6)) = temp16;
320 	ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
321 	res = read(break_fd, &breaks, sizeof(unsigned long long));
322 	assert(res == sizeof(unsigned long long));
323 	if (breaks == 0) {
324 		printf("TESTED: No overlap\n");
325 	} else {
326 		printf("FAILED: No overlap: %lld != 0\n", breaks);
327 		fail = 1;
328 	}
329 
330 	/* Hit */
331 	ioctl(break_fd, PERF_EVENT_IOC_RESET);
332 	ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
333 	temp64 = *((__u64 *)target);
334 	*((__u64 *)target) = temp64;
335 	ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
336 	res = read(break_fd, &breaks, sizeof(unsigned long long));
337 	assert(res == sizeof(unsigned long long));
338 	if (breaks == 2) {
339 		printf("TESTED: Full overlap\n");
340 	} else {
341 		printf("FAILED: Full overlap: %lld != 2\n", breaks);
342 		fail = 1;
343 	}
344 
345 	free(target);
346 	close(break_fd);
347 	return fail;
348 }
349 
multi_dawr_workload(void)350 static void multi_dawr_workload(void)
351 {
352 	a += 10;
353 	b += 10;
354 	c[512 + 1] += 'a';
355 }
356 
test_process_multi_diff_addr(void)357 static int test_process_multi_diff_addr(void)
358 {
359 	unsigned long long breaks1 = 0, breaks2 = 0;
360 	int fd1, fd2;
361 	char *desc = "Process specific, Two events, diff addr";
362 	size_t res;
363 
364 	fd1 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
365 	if (fd1 < 0) {
366 		perror("perf_process_event_open");
367 		exit(EXIT_FAILURE);
368 	}
369 
370 	fd2 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&b, (__u64)sizeof(b));
371 	if (fd2 < 0) {
372 		close(fd1);
373 		perror("perf_process_event_open");
374 		exit(EXIT_FAILURE);
375 	}
376 
377 	ioctl(fd1, PERF_EVENT_IOC_RESET);
378 	ioctl(fd2, PERF_EVENT_IOC_RESET);
379 	ioctl(fd1, PERF_EVENT_IOC_ENABLE);
380 	ioctl(fd2, PERF_EVENT_IOC_ENABLE);
381 	multi_dawr_workload();
382 	ioctl(fd1, PERF_EVENT_IOC_DISABLE);
383 	ioctl(fd2, PERF_EVENT_IOC_DISABLE);
384 
385 	res = read(fd1, &breaks1, sizeof(breaks1));
386 	assert(res == sizeof(unsigned long long));
387 	res = read(fd2, &breaks2, sizeof(breaks2));
388 	assert(res == sizeof(unsigned long long));
389 
390 	close(fd1);
391 	close(fd2);
392 
393 	if (breaks1 != 2 || breaks2 != 2) {
394 		printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);
395 		return 1;
396 	}
397 
398 	printf("TESTED: %s\n", desc);
399 	return 0;
400 }
401 
test_process_multi_same_addr(void)402 static int test_process_multi_same_addr(void)
403 {
404 	unsigned long long breaks1 = 0, breaks2 = 0;
405 	int fd1, fd2;
406 	char *desc = "Process specific, Two events, same addr";
407 	size_t res;
408 
409 	fd1 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
410 	if (fd1 < 0) {
411 		perror("perf_process_event_open");
412 		exit(EXIT_FAILURE);
413 	}
414 
415 	fd2 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
416 	if (fd2 < 0) {
417 		close(fd1);
418 		perror("perf_process_event_open");
419 		exit(EXIT_FAILURE);
420 	}
421 
422 	ioctl(fd1, PERF_EVENT_IOC_RESET);
423 	ioctl(fd2, PERF_EVENT_IOC_RESET);
424 	ioctl(fd1, PERF_EVENT_IOC_ENABLE);
425 	ioctl(fd2, PERF_EVENT_IOC_ENABLE);
426 	multi_dawr_workload();
427 	ioctl(fd1, PERF_EVENT_IOC_DISABLE);
428 	ioctl(fd2, PERF_EVENT_IOC_DISABLE);
429 
430 	res = read(fd1, &breaks1, sizeof(breaks1));
431 	assert(res == sizeof(unsigned long long));
432 	res = read(fd2, &breaks2, sizeof(breaks2));
433 	assert(res == sizeof(unsigned long long));
434 
435 	close(fd1);
436 	close(fd2);
437 
438 	if (breaks1 != 2 || breaks2 != 2) {
439 		printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);
440 		return 1;
441 	}
442 
443 	printf("TESTED: %s\n", desc);
444 	return 0;
445 }
446 
test_process_multi_diff_addr_ro_wo(void)447 static int test_process_multi_diff_addr_ro_wo(void)
448 {
449 	unsigned long long breaks1 = 0, breaks2 = 0;
450 	int fd1, fd2;
451 	char *desc = "Process specific, Two events, diff addr, one is RO, other is WO";
452 	size_t res;
453 
454 	fd1 = perf_process_event_open(HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));
455 	if (fd1 < 0) {
456 		perror("perf_process_event_open");
457 		exit(EXIT_FAILURE);
458 	}
459 
460 	fd2 = perf_process_event_open(HW_BREAKPOINT_R, (__u64)&b, (__u64)sizeof(b));
461 	if (fd2 < 0) {
462 		close(fd1);
463 		perror("perf_process_event_open");
464 		exit(EXIT_FAILURE);
465 	}
466 
467 	ioctl(fd1, PERF_EVENT_IOC_RESET);
468 	ioctl(fd2, PERF_EVENT_IOC_RESET);
469 	ioctl(fd1, PERF_EVENT_IOC_ENABLE);
470 	ioctl(fd2, PERF_EVENT_IOC_ENABLE);
471 	multi_dawr_workload();
472 	ioctl(fd1, PERF_EVENT_IOC_DISABLE);
473 	ioctl(fd2, PERF_EVENT_IOC_DISABLE);
474 
475 	res = read(fd1, &breaks1, sizeof(breaks1));
476 	assert(res == sizeof(unsigned long long));
477 	res = read(fd2, &breaks2, sizeof(breaks2));
478 	assert(res == sizeof(unsigned long long));
479 
480 	close(fd1);
481 	close(fd2);
482 
483 	if (breaks1 != 1 || breaks2 != 1) {
484 		printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);
485 		return 1;
486 	}
487 
488 	printf("TESTED: %s\n", desc);
489 	return 0;
490 }
491 
test_process_multi_same_addr_ro_wo(void)492 static int test_process_multi_same_addr_ro_wo(void)
493 {
494 	unsigned long long breaks1 = 0, breaks2 = 0;
495 	int fd1, fd2;
496 	char *desc = "Process specific, Two events, same addr, one is RO, other is WO";
497 	size_t res;
498 
499 	fd1 = perf_process_event_open(HW_BREAKPOINT_R, (__u64)&a, (__u64)sizeof(a));
500 	if (fd1 < 0) {
501 		perror("perf_process_event_open");
502 		exit(EXIT_FAILURE);
503 	}
504 
505 	fd2 = perf_process_event_open(HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));
506 	if (fd2 < 0) {
507 		close(fd1);
508 		perror("perf_process_event_open");
509 		exit(EXIT_FAILURE);
510 	}
511 
512 	ioctl(fd1, PERF_EVENT_IOC_RESET);
513 	ioctl(fd2, PERF_EVENT_IOC_RESET);
514 	ioctl(fd1, PERF_EVENT_IOC_ENABLE);
515 	ioctl(fd2, PERF_EVENT_IOC_ENABLE);
516 	multi_dawr_workload();
517 	ioctl(fd1, PERF_EVENT_IOC_DISABLE);
518 	ioctl(fd2, PERF_EVENT_IOC_DISABLE);
519 
520 	res = read(fd1, &breaks1, sizeof(breaks1));
521 	assert(res == sizeof(unsigned long long));
522 	res = read(fd2, &breaks2, sizeof(breaks2));
523 	assert(res == sizeof(unsigned long long));
524 
525 	close(fd1);
526 	close(fd2);
527 
528 	if (breaks1 != 1 || breaks2 != 1) {
529 		printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);
530 		return 1;
531 	}
532 
533 	printf("TESTED: %s\n", desc);
534 	return 0;
535 }
536 
test_syswide_multi_diff_addr(void)537 static int test_syswide_multi_diff_addr(void)
538 {
539 	unsigned long long breaks1 = 0, breaks2 = 0;
540 	int *fd1 = malloc(nprocs * sizeof(int));
541 	int *fd2 = malloc(nprocs * sizeof(int));
542 	char *desc = "Systemwide, Two events, diff addr";
543 	int ret;
544 
545 	ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
546 	if (ret) {
547 		perror("perf_systemwide_event_open");
548 		exit(EXIT_FAILURE);
549 	}
550 
551 	ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_RW, (__u64)&b, (__u64)sizeof(b));
552 	if (ret) {
553 		close_fds(fd1, nprocs);
554 		perror("perf_systemwide_event_open");
555 		exit(EXIT_FAILURE);
556 	}
557 
558 	reset_fds(fd1, nprocs);
559 	reset_fds(fd2, nprocs);
560 	enable_fds(fd1, nprocs);
561 	enable_fds(fd2, nprocs);
562 	multi_dawr_workload();
563 	disable_fds(fd1, nprocs);
564 	disable_fds(fd2, nprocs);
565 
566 	breaks1 = read_fds(fd1, nprocs);
567 	breaks2 = read_fds(fd2, nprocs);
568 
569 	close_fds(fd1, nprocs);
570 	close_fds(fd2, nprocs);
571 
572 	free(fd1);
573 	free(fd2);
574 
575 	if (breaks1 != 2 || breaks2 != 2) {
576 		printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);
577 		return 1;
578 	}
579 
580 	printf("TESTED: %s\n", desc);
581 	return 0;
582 }
583 
test_syswide_multi_same_addr(void)584 static int test_syswide_multi_same_addr(void)
585 {
586 	unsigned long long breaks1 = 0, breaks2 = 0;
587 	int *fd1 = malloc(nprocs * sizeof(int));
588 	int *fd2 = malloc(nprocs * sizeof(int));
589 	char *desc = "Systemwide, Two events, same addr";
590 	int ret;
591 
592 	ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
593 	if (ret) {
594 		perror("perf_systemwide_event_open");
595 		exit(EXIT_FAILURE);
596 	}
597 
598 	ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
599 	if (ret) {
600 		close_fds(fd1, nprocs);
601 		perror("perf_systemwide_event_open");
602 		exit(EXIT_FAILURE);
603 	}
604 
605 	reset_fds(fd1, nprocs);
606 	reset_fds(fd2, nprocs);
607 	enable_fds(fd1, nprocs);
608 	enable_fds(fd2, nprocs);
609 	multi_dawr_workload();
610 	disable_fds(fd1, nprocs);
611 	disable_fds(fd2, nprocs);
612 
613 	breaks1 = read_fds(fd1, nprocs);
614 	breaks2 = read_fds(fd2, nprocs);
615 
616 	close_fds(fd1, nprocs);
617 	close_fds(fd2, nprocs);
618 
619 	free(fd1);
620 	free(fd2);
621 
622 	if (breaks1 != 2 || breaks2 != 2) {
623 		printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);
624 		return 1;
625 	}
626 
627 	printf("TESTED: %s\n", desc);
628 	return 0;
629 }
630 
test_syswide_multi_diff_addr_ro_wo(void)631 static int test_syswide_multi_diff_addr_ro_wo(void)
632 {
633 	unsigned long long breaks1 = 0, breaks2 = 0;
634 	int *fd1 = malloc(nprocs * sizeof(int));
635 	int *fd2 = malloc(nprocs * sizeof(int));
636 	char *desc = "Systemwide, Two events, diff addr, one is RO, other is WO";
637 	int ret;
638 
639 	ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));
640 	if (ret) {
641 		perror("perf_systemwide_event_open");
642 		exit(EXIT_FAILURE);
643 	}
644 
645 	ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_R, (__u64)&b, (__u64)sizeof(b));
646 	if (ret) {
647 		close_fds(fd1, nprocs);
648 		perror("perf_systemwide_event_open");
649 		exit(EXIT_FAILURE);
650 	}
651 
652 	reset_fds(fd1, nprocs);
653 	reset_fds(fd2, nprocs);
654 	enable_fds(fd1, nprocs);
655 	enable_fds(fd2, nprocs);
656 	multi_dawr_workload();
657 	disable_fds(fd1, nprocs);
658 	disable_fds(fd2, nprocs);
659 
660 	breaks1 = read_fds(fd1, nprocs);
661 	breaks2 = read_fds(fd2, nprocs);
662 
663 	close_fds(fd1, nprocs);
664 	close_fds(fd2, nprocs);
665 
666 	free(fd1);
667 	free(fd2);
668 
669 	if (breaks1 != 1 || breaks2 != 1) {
670 		printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);
671 		return 1;
672 	}
673 
674 	printf("TESTED: %s\n", desc);
675 	return 0;
676 }
677 
test_syswide_multi_same_addr_ro_wo(void)678 static int test_syswide_multi_same_addr_ro_wo(void)
679 {
680 	unsigned long long breaks1 = 0, breaks2 = 0;
681 	int *fd1 = malloc(nprocs * sizeof(int));
682 	int *fd2 = malloc(nprocs * sizeof(int));
683 	char *desc = "Systemwide, Two events, same addr, one is RO, other is WO";
684 	int ret;
685 
686 	ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));
687 	if (ret) {
688 		perror("perf_systemwide_event_open");
689 		exit(EXIT_FAILURE);
690 	}
691 
692 	ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_R, (__u64)&a, (__u64)sizeof(a));
693 	if (ret) {
694 		close_fds(fd1, nprocs);
695 		perror("perf_systemwide_event_open");
696 		exit(EXIT_FAILURE);
697 	}
698 
699 	reset_fds(fd1, nprocs);
700 	reset_fds(fd2, nprocs);
701 	enable_fds(fd1, nprocs);
702 	enable_fds(fd2, nprocs);
703 	multi_dawr_workload();
704 	disable_fds(fd1, nprocs);
705 	disable_fds(fd2, nprocs);
706 
707 	breaks1 = read_fds(fd1, nprocs);
708 	breaks2 = read_fds(fd2, nprocs);
709 
710 	close_fds(fd1, nprocs);
711 	close_fds(fd2, nprocs);
712 
713 	free(fd1);
714 	free(fd2);
715 
716 	if (breaks1 != 1 || breaks2 != 1) {
717 		printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);
718 		return 1;
719 	}
720 
721 	printf("TESTED: %s\n", desc);
722 	return 0;
723 }
724 
runtest_multi_dawr(void)725 static int runtest_multi_dawr(void)
726 {
727 	int ret = 0;
728 
729 	ret |= test_process_multi_diff_addr();
730 	ret |= test_process_multi_same_addr();
731 	ret |= test_process_multi_diff_addr_ro_wo();
732 	ret |= test_process_multi_same_addr_ro_wo();
733 	ret |= test_syswide_multi_diff_addr();
734 	ret |= test_syswide_multi_same_addr();
735 	ret |= test_syswide_multi_diff_addr_ro_wo();
736 	ret |= test_syswide_multi_same_addr_ro_wo();
737 
738 	return ret;
739 }
740 
runtest_unaligned_512bytes(void)741 static int runtest_unaligned_512bytes(void)
742 {
743 	unsigned long long breaks = 0;
744 	int fd;
745 	char *desc = "Process specific, 512 bytes, unaligned";
746 	__u64 addr = (__u64)&c + 8;
747 	size_t res;
748 
749 	fd = perf_process_event_open(HW_BREAKPOINT_RW, addr, 512);
750 	if (fd < 0) {
751 		perror("perf_process_event_open");
752 		exit(EXIT_FAILURE);
753 	}
754 
755 	ioctl(fd, PERF_EVENT_IOC_RESET);
756 	ioctl(fd, PERF_EVENT_IOC_ENABLE);
757 	multi_dawr_workload();
758 	ioctl(fd, PERF_EVENT_IOC_DISABLE);
759 
760 	res = read(fd, &breaks, sizeof(breaks));
761 	assert(res == sizeof(unsigned long long));
762 
763 	close(fd);
764 
765 	if (breaks != 2) {
766 		printf("FAILED: %s: %lld != 2\n", desc, breaks);
767 		return 1;
768 	}
769 
770 	printf("TESTED: %s\n", desc);
771 	return 0;
772 }
773 
774 /* There is no perf api to find number of available watchpoints. Use ptrace. */
get_nr_wps(bool * arch_31)775 static int get_nr_wps(bool *arch_31)
776 {
777 	struct ppc_debug_info dbginfo;
778 	int child_pid;
779 
780 	child_pid = fork();
781 	if (!child_pid) {
782 		int ret = ptrace(PTRACE_TRACEME, 0, NULL, 0);
783 		if (ret) {
784 			perror("PTRACE_TRACEME failed\n");
785 			exit(EXIT_FAILURE);
786 		}
787 		kill(getpid(), SIGUSR1);
788 
789 		sleep(1);
790 		exit(EXIT_SUCCESS);
791 	}
792 
793 	wait(NULL);
794 	if (ptrace(PPC_PTRACE_GETHWDBGINFO, child_pid, NULL, &dbginfo)) {
795 		perror("Can't get breakpoint info");
796 		exit(EXIT_FAILURE);
797 	}
798 
799 	*arch_31 = !!(dbginfo.features & PPC_DEBUG_FEATURE_DATA_BP_ARCH_31);
800 	return dbginfo.num_data_bps;
801 }
802 
runtest(void)803 static int runtest(void)
804 {
805 	int rwflag;
806 	int exclude_user;
807 	int ret;
808 	bool dawr = dawr_supported();
809 	bool arch_31 = false;
810 	int nr_wps = get_nr_wps(&arch_31);
811 
812 	/*
813 	 * perf defines rwflag as two bits read and write and at least
814 	 * one must be set.  So range 1-3.
815 	 */
816 	for (rwflag = 1 ; rwflag < 4; rwflag++) {
817 		for (exclude_user = 0 ; exclude_user < 2; exclude_user++) {
818 			ret = runtestsingle(rwflag, exclude_user, 0);
819 			if (ret)
820 				return ret;
821 
822 			/* if we have the dawr, we can do an array test */
823 			if (!dawr)
824 				continue;
825 			ret = runtestsingle(rwflag, exclude_user, 1);
826 			if (ret)
827 				return ret;
828 		}
829 	}
830 
831 	ret = runtest_dar_outside();
832 	if (ret)
833 		return ret;
834 
835 	if (dawr && nr_wps > 1) {
836 		nprocs = get_nprocs();
837 		ret = runtest_multi_dawr();
838 		if (ret)
839 			return ret;
840 	}
841 
842 	if (dawr && arch_31)
843 		ret = runtest_unaligned_512bytes();
844 
845 	return ret;
846 }
847 
848 
perf_hwbreak(void)849 static int perf_hwbreak(void)
850 {
851 	srand ( time(NULL) );
852 
853 	SKIP_IF(!perf_breakpoint_supported());
854 
855 	return runtest();
856 }
857 
main(int argc,char * argv[],char ** envp)858 int main(int argc, char *argv[], char **envp)
859 {
860 	return test_harness(perf_hwbreak, "perf_hwbreak");
861 }
862