1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
46int nprocs;
47
48static volatile int a = 10;
49static volatile int b = 10;
50static volatile char c[512 + 8] __attribute__((aligned(512)));
51
52static 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
69static int
70perf_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
78static 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
86static 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
94static 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
102static 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
117static 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
125static 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
133static 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
141static int perf_systemwide_event_open(int *fd, __u32 type, __u64 addr, __u64 len)
142{
143 int i = 0;
144
145
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
156static inline bool breakpoint_test(int len)
157{
158 int fd;
159
160
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
168static inline bool perf_breakpoint_supported(void)
169{
170 return breakpoint_test(4);
171}
172
173static inline bool dawr_supported(void)
174{
175 return breakpoint_test(DAWR_LENGTH_MAX);
176}
177
178static 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);
189 volatile int *k;
190 __u64 len;
191
192
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
209 ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
210
211
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
222 ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
223
224
225 res = read(break_fd, &breaks, sizeof(unsigned long long));
226 assert(res == sizeof(unsigned long long));
227
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
246static 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
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
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
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
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
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
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
350static void multi_dawr_workload(void)
351{
352 a += 10;
353 b += 10;
354 c[512 + 1] += 'a';
355}
356
357static 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
402static 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
447static 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
492static 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
537static 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
584static 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
631static 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
678static 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
725static 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
741static 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
775static 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
803static 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
814
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
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
849static int perf_hwbreak(void)
850{
851 srand ( time(NULL) );
852
853 SKIP_IF(!perf_breakpoint_supported());
854
855 return runtest();
856}
857
858int main(int argc, char *argv[], char **envp)
859{
860 return test_harness(perf_hwbreak, "perf_hwbreak");
861}
862