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