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