Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * perf events self profiling example test case for hw breakpoints.
0004  *
0005  * This tests perf PERF_TYPE_BREAKPOINT parameters
0006  * 1) tests all variants of the break on read/write flags
0007  * 2) tests exclude_user == 0 and 1
0008  * 3) test array matches (if DAWR is supported))
0009  * 4) test different numbers of breakpoints matches
0010  *
0011  * Configure this breakpoint, then read and write the data a number of
0012  * times. Then check the output count from perf is as expected.
0013  *
0014  * Based on:
0015  *   http://ozlabs.org/~anton/junkcode/perf_events_example1.c
0016  *
0017  * Copyright (C) 2018 Michael Neuling, IBM Corporation.
0018  */
0019 
0020 #include <unistd.h>
0021 #include <assert.h>
0022 #include <stdio.h>
0023 #include <stdlib.h>
0024 #include <signal.h>
0025 #include <string.h>
0026 #include <sys/ioctl.h>
0027 #include <sys/wait.h>
0028 #include <sys/ptrace.h>
0029 #include <sys/sysinfo.h>
0030 #include <asm/ptrace.h>
0031 #include <elf.h>
0032 #include <pthread.h>
0033 #include <sys/syscall.h>
0034 #include <linux/perf_event.h>
0035 #include <linux/hw_breakpoint.h>
0036 #include "utils.h"
0037 
0038 #ifndef PPC_DEBUG_FEATURE_DATA_BP_ARCH_31
0039 #define PPC_DEBUG_FEATURE_DATA_BP_ARCH_31   0x20
0040 #endif
0041 
0042 #define MAX_LOOPS 10000
0043 
0044 #define DAWR_LENGTH_MAX ((0x3f + 1) * 8)
0045 
0046 int nprocs;
0047 
0048 static volatile int a = 10;
0049 static volatile int b = 10;
0050 static volatile char c[512 + 8] __attribute__((aligned(512)));
0051 
0052 static void perf_event_attr_set(struct perf_event_attr *attr,
0053                 __u32 type, __u64 addr, __u64 len,
0054                 bool exclude_user)
0055 {
0056     memset(attr, 0, sizeof(struct perf_event_attr));
0057     attr->type           = PERF_TYPE_BREAKPOINT;
0058     attr->size           = sizeof(struct perf_event_attr);
0059     attr->bp_type        = type;
0060     attr->bp_addr        = addr;
0061     attr->bp_len         = len;
0062     attr->exclude_kernel = 1;
0063     attr->exclude_hv     = 1;
0064     attr->exclude_guest  = 1;
0065     attr->exclude_user   = exclude_user;
0066     attr->disabled       = 1;
0067 }
0068 
0069 static int
0070 perf_process_event_open_exclude_user(__u32 type, __u64 addr, __u64 len, bool exclude_user)
0071 {
0072     struct perf_event_attr attr;
0073 
0074     perf_event_attr_set(&attr, type, addr, len, exclude_user);
0075     return syscall(__NR_perf_event_open, &attr, getpid(), -1, -1, 0);
0076 }
0077 
0078 static int perf_process_event_open(__u32 type, __u64 addr, __u64 len)
0079 {
0080     struct perf_event_attr attr;
0081 
0082     perf_event_attr_set(&attr, type, addr, len, 0);
0083     return syscall(__NR_perf_event_open, &attr, getpid(), -1, -1, 0);
0084 }
0085 
0086 static int perf_cpu_event_open(long cpu, __u32 type, __u64 addr, __u64 len)
0087 {
0088     struct perf_event_attr attr;
0089 
0090     perf_event_attr_set(&attr, type, addr, len, 0);
0091     return syscall(__NR_perf_event_open, &attr, -1, cpu, -1, 0);
0092 }
0093 
0094 static void close_fds(int *fd, int n)
0095 {
0096     int i;
0097 
0098     for (i = 0; i < n; i++)
0099         close(fd[i]);
0100 }
0101 
0102 static unsigned long read_fds(int *fd, int n)
0103 {
0104     int i;
0105     unsigned long c = 0;
0106     unsigned long count = 0;
0107     size_t res;
0108 
0109     for (i = 0; i < n; i++) {
0110         res = read(fd[i], &c, sizeof(c));
0111         assert(res == sizeof(unsigned long long));
0112         count += c;
0113     }
0114     return count;
0115 }
0116 
0117 static void reset_fds(int *fd, int n)
0118 {
0119     int i;
0120 
0121     for (i = 0; i < n; i++)
0122         ioctl(fd[i], PERF_EVENT_IOC_RESET);
0123 }
0124 
0125 static void enable_fds(int *fd, int n)
0126 {
0127     int i;
0128 
0129     for (i = 0; i < n; i++)
0130         ioctl(fd[i], PERF_EVENT_IOC_ENABLE);
0131 }
0132 
0133 static void disable_fds(int *fd, int n)
0134 {
0135     int i;
0136 
0137     for (i = 0; i < n; i++)
0138         ioctl(fd[i], PERF_EVENT_IOC_DISABLE);
0139 }
0140 
0141 static int perf_systemwide_event_open(int *fd, __u32 type, __u64 addr, __u64 len)
0142 {
0143     int i = 0;
0144 
0145     /* Assume online processors are 0 to nprocs for simplisity */
0146     for (i = 0; i < nprocs; i++) {
0147         fd[i] = perf_cpu_event_open(i, type, addr, len);
0148         if (fd[i] < 0) {
0149             close_fds(fd, i);
0150             return fd[i];
0151         }
0152     }
0153     return 0;
0154 }
0155 
0156 static inline bool breakpoint_test(int len)
0157 {
0158     int fd;
0159 
0160     /* bp_addr can point anywhere but needs to be aligned */
0161     fd = perf_process_event_open(HW_BREAKPOINT_R, (__u64)(&fd) & 0xfffffffffffff800, len);
0162     if (fd < 0)
0163         return false;
0164     close(fd);
0165     return true;
0166 }
0167 
0168 static inline bool perf_breakpoint_supported(void)
0169 {
0170     return breakpoint_test(4);
0171 }
0172 
0173 static inline bool dawr_supported(void)
0174 {
0175     return breakpoint_test(DAWR_LENGTH_MAX);
0176 }
0177 
0178 static int runtestsingle(int readwriteflag, int exclude_user, int arraytest)
0179 {
0180     int i,j;
0181     size_t res;
0182     unsigned long long breaks, needed;
0183     int readint;
0184     int readintarraybig[2*DAWR_LENGTH_MAX/sizeof(int)];
0185     int *readintalign;
0186     volatile int *ptr;
0187     int break_fd;
0188     int loop_num = MAX_LOOPS - (rand() % 100); /* provide some variability */
0189     volatile int *k;
0190     __u64 len;
0191 
0192     /* align to 0x400 boundary as required by DAWR */
0193     readintalign = (int *)(((unsigned long)readintarraybig + 0x7ff) &
0194                    0xfffffffffffff800);
0195 
0196     ptr = &readint;
0197     if (arraytest)
0198         ptr = &readintalign[0];
0199 
0200     len = arraytest ? DAWR_LENGTH_MAX : sizeof(int);
0201     break_fd = perf_process_event_open_exclude_user(readwriteflag, (__u64)ptr,
0202                             len, exclude_user);
0203     if (break_fd < 0) {
0204         perror("perf_process_event_open_exclude_user");
0205         exit(1);
0206     }
0207 
0208     /* start counters */
0209     ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
0210 
0211     /* Test a bunch of reads and writes */
0212     k = &readint;
0213     for (i = 0; i < loop_num; i++) {
0214         if (arraytest)
0215             k = &(readintalign[i % (DAWR_LENGTH_MAX/sizeof(int))]);
0216 
0217         j = *k;
0218         *k = j;
0219     }
0220 
0221     /* stop counters */
0222     ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
0223 
0224     /* read and check counters */
0225     res = read(break_fd, &breaks, sizeof(unsigned long long));
0226     assert(res == sizeof(unsigned long long));
0227     /* we read and write each loop, so subtract the ones we are counting */
0228     needed = 0;
0229     if (readwriteflag & HW_BREAKPOINT_R)
0230         needed += loop_num;
0231     if (readwriteflag & HW_BREAKPOINT_W)
0232         needed += loop_num;
0233     needed = needed * (1 - exclude_user);
0234     printf("TESTED: addr:0x%lx brks:% 8lld loops:% 8i rw:%i !user:%i array:%i\n",
0235            (unsigned long int)ptr, breaks, loop_num, readwriteflag, exclude_user, arraytest);
0236     if (breaks != needed) {
0237         printf("FAILED: 0x%lx brks:%lld needed:%lli %i %i %i\n\n",
0238                (unsigned long int)ptr, breaks, needed, loop_num, readwriteflag, exclude_user);
0239         return 1;
0240     }
0241     close(break_fd);
0242 
0243     return 0;
0244 }
0245 
0246 static int runtest_dar_outside(void)
0247 {
0248     void *target;
0249     volatile __u16 temp16;
0250     volatile __u64 temp64;
0251     int break_fd;
0252     unsigned long long breaks;
0253     int fail = 0;
0254     size_t res;
0255 
0256     target = malloc(8);
0257     if (!target) {
0258         perror("malloc failed");
0259         exit(EXIT_FAILURE);
0260     }
0261 
0262     /* watch middle half of target array */
0263     break_fd = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)(target + 2), 4);
0264     if (break_fd < 0) {
0265         free(target);
0266         perror("perf_process_event_open");
0267         exit(EXIT_FAILURE);
0268     }
0269 
0270     /* Shouldn't hit. */
0271     ioctl(break_fd, PERF_EVENT_IOC_RESET);
0272     ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
0273     temp16 = *((__u16 *)target);
0274     *((__u16 *)target) = temp16;
0275     ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
0276     res = read(break_fd, &breaks, sizeof(unsigned long long));
0277     assert(res == sizeof(unsigned long long));
0278     if (breaks == 0) {
0279         printf("TESTED: No overlap\n");
0280     } else {
0281         printf("FAILED: No overlap: %lld != 0\n", breaks);
0282         fail = 1;
0283     }
0284 
0285     /* Hit */
0286     ioctl(break_fd, PERF_EVENT_IOC_RESET);
0287     ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
0288     temp16 = *((__u16 *)(target + 1));
0289     *((__u16 *)(target + 1)) = temp16;
0290     ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
0291     res = read(break_fd, &breaks, sizeof(unsigned long long));
0292     assert(res == sizeof(unsigned long long));
0293     if (breaks == 2) {
0294         printf("TESTED: Partial overlap\n");
0295     } else {
0296         printf("FAILED: Partial overlap: %lld != 2\n", breaks);
0297         fail = 1;
0298     }
0299 
0300     /* Hit */
0301     ioctl(break_fd, PERF_EVENT_IOC_RESET);
0302     ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
0303     temp16 = *((__u16 *)(target + 5));
0304     *((__u16 *)(target + 5)) = temp16;
0305     ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
0306     res = read(break_fd, &breaks, sizeof(unsigned long long));
0307     assert(res == sizeof(unsigned long long));
0308     if (breaks == 2) {
0309         printf("TESTED: Partial overlap\n");
0310     } else {
0311         printf("FAILED: Partial overlap: %lld != 2\n", breaks);
0312         fail = 1;
0313     }
0314 
0315     /* Shouldn't Hit */
0316     ioctl(break_fd, PERF_EVENT_IOC_RESET);
0317     ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
0318     temp16 = *((__u16 *)(target + 6));
0319     *((__u16 *)(target + 6)) = temp16;
0320     ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
0321     res = read(break_fd, &breaks, sizeof(unsigned long long));
0322     assert(res == sizeof(unsigned long long));
0323     if (breaks == 0) {
0324         printf("TESTED: No overlap\n");
0325     } else {
0326         printf("FAILED: No overlap: %lld != 0\n", breaks);
0327         fail = 1;
0328     }
0329 
0330     /* Hit */
0331     ioctl(break_fd, PERF_EVENT_IOC_RESET);
0332     ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
0333     temp64 = *((__u64 *)target);
0334     *((__u64 *)target) = temp64;
0335     ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
0336     res = read(break_fd, &breaks, sizeof(unsigned long long));
0337     assert(res == sizeof(unsigned long long));
0338     if (breaks == 2) {
0339         printf("TESTED: Full overlap\n");
0340     } else {
0341         printf("FAILED: Full overlap: %lld != 2\n", breaks);
0342         fail = 1;
0343     }
0344 
0345     free(target);
0346     close(break_fd);
0347     return fail;
0348 }
0349 
0350 static void multi_dawr_workload(void)
0351 {
0352     a += 10;
0353     b += 10;
0354     c[512 + 1] += 'a';
0355 }
0356 
0357 static int test_process_multi_diff_addr(void)
0358 {
0359     unsigned long long breaks1 = 0, breaks2 = 0;
0360     int fd1, fd2;
0361     char *desc = "Process specific, Two events, diff addr";
0362     size_t res;
0363 
0364     fd1 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
0365     if (fd1 < 0) {
0366         perror("perf_process_event_open");
0367         exit(EXIT_FAILURE);
0368     }
0369 
0370     fd2 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&b, (__u64)sizeof(b));
0371     if (fd2 < 0) {
0372         close(fd1);
0373         perror("perf_process_event_open");
0374         exit(EXIT_FAILURE);
0375     }
0376 
0377     ioctl(fd1, PERF_EVENT_IOC_RESET);
0378     ioctl(fd2, PERF_EVENT_IOC_RESET);
0379     ioctl(fd1, PERF_EVENT_IOC_ENABLE);
0380     ioctl(fd2, PERF_EVENT_IOC_ENABLE);
0381     multi_dawr_workload();
0382     ioctl(fd1, PERF_EVENT_IOC_DISABLE);
0383     ioctl(fd2, PERF_EVENT_IOC_DISABLE);
0384 
0385     res = read(fd1, &breaks1, sizeof(breaks1));
0386     assert(res == sizeof(unsigned long long));
0387     res = read(fd2, &breaks2, sizeof(breaks2));
0388     assert(res == sizeof(unsigned long long));
0389 
0390     close(fd1);
0391     close(fd2);
0392 
0393     if (breaks1 != 2 || breaks2 != 2) {
0394         printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);
0395         return 1;
0396     }
0397 
0398     printf("TESTED: %s\n", desc);
0399     return 0;
0400 }
0401 
0402 static int test_process_multi_same_addr(void)
0403 {
0404     unsigned long long breaks1 = 0, breaks2 = 0;
0405     int fd1, fd2;
0406     char *desc = "Process specific, Two events, same addr";
0407     size_t res;
0408 
0409     fd1 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
0410     if (fd1 < 0) {
0411         perror("perf_process_event_open");
0412         exit(EXIT_FAILURE);
0413     }
0414 
0415     fd2 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
0416     if (fd2 < 0) {
0417         close(fd1);
0418         perror("perf_process_event_open");
0419         exit(EXIT_FAILURE);
0420     }
0421 
0422     ioctl(fd1, PERF_EVENT_IOC_RESET);
0423     ioctl(fd2, PERF_EVENT_IOC_RESET);
0424     ioctl(fd1, PERF_EVENT_IOC_ENABLE);
0425     ioctl(fd2, PERF_EVENT_IOC_ENABLE);
0426     multi_dawr_workload();
0427     ioctl(fd1, PERF_EVENT_IOC_DISABLE);
0428     ioctl(fd2, PERF_EVENT_IOC_DISABLE);
0429 
0430     res = read(fd1, &breaks1, sizeof(breaks1));
0431     assert(res == sizeof(unsigned long long));
0432     res = read(fd2, &breaks2, sizeof(breaks2));
0433     assert(res == sizeof(unsigned long long));
0434 
0435     close(fd1);
0436     close(fd2);
0437 
0438     if (breaks1 != 2 || breaks2 != 2) {
0439         printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);
0440         return 1;
0441     }
0442 
0443     printf("TESTED: %s\n", desc);
0444     return 0;
0445 }
0446 
0447 static int test_process_multi_diff_addr_ro_wo(void)
0448 {
0449     unsigned long long breaks1 = 0, breaks2 = 0;
0450     int fd1, fd2;
0451     char *desc = "Process specific, Two events, diff addr, one is RO, other is WO";
0452     size_t res;
0453 
0454     fd1 = perf_process_event_open(HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));
0455     if (fd1 < 0) {
0456         perror("perf_process_event_open");
0457         exit(EXIT_FAILURE);
0458     }
0459 
0460     fd2 = perf_process_event_open(HW_BREAKPOINT_R, (__u64)&b, (__u64)sizeof(b));
0461     if (fd2 < 0) {
0462         close(fd1);
0463         perror("perf_process_event_open");
0464         exit(EXIT_FAILURE);
0465     }
0466 
0467     ioctl(fd1, PERF_EVENT_IOC_RESET);
0468     ioctl(fd2, PERF_EVENT_IOC_RESET);
0469     ioctl(fd1, PERF_EVENT_IOC_ENABLE);
0470     ioctl(fd2, PERF_EVENT_IOC_ENABLE);
0471     multi_dawr_workload();
0472     ioctl(fd1, PERF_EVENT_IOC_DISABLE);
0473     ioctl(fd2, PERF_EVENT_IOC_DISABLE);
0474 
0475     res = read(fd1, &breaks1, sizeof(breaks1));
0476     assert(res == sizeof(unsigned long long));
0477     res = read(fd2, &breaks2, sizeof(breaks2));
0478     assert(res == sizeof(unsigned long long));
0479 
0480     close(fd1);
0481     close(fd2);
0482 
0483     if (breaks1 != 1 || breaks2 != 1) {
0484         printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);
0485         return 1;
0486     }
0487 
0488     printf("TESTED: %s\n", desc);
0489     return 0;
0490 }
0491 
0492 static int test_process_multi_same_addr_ro_wo(void)
0493 {
0494     unsigned long long breaks1 = 0, breaks2 = 0;
0495     int fd1, fd2;
0496     char *desc = "Process specific, Two events, same addr, one is RO, other is WO";
0497     size_t res;
0498 
0499     fd1 = perf_process_event_open(HW_BREAKPOINT_R, (__u64)&a, (__u64)sizeof(a));
0500     if (fd1 < 0) {
0501         perror("perf_process_event_open");
0502         exit(EXIT_FAILURE);
0503     }
0504 
0505     fd2 = perf_process_event_open(HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));
0506     if (fd2 < 0) {
0507         close(fd1);
0508         perror("perf_process_event_open");
0509         exit(EXIT_FAILURE);
0510     }
0511 
0512     ioctl(fd1, PERF_EVENT_IOC_RESET);
0513     ioctl(fd2, PERF_EVENT_IOC_RESET);
0514     ioctl(fd1, PERF_EVENT_IOC_ENABLE);
0515     ioctl(fd2, PERF_EVENT_IOC_ENABLE);
0516     multi_dawr_workload();
0517     ioctl(fd1, PERF_EVENT_IOC_DISABLE);
0518     ioctl(fd2, PERF_EVENT_IOC_DISABLE);
0519 
0520     res = read(fd1, &breaks1, sizeof(breaks1));
0521     assert(res == sizeof(unsigned long long));
0522     res = read(fd2, &breaks2, sizeof(breaks2));
0523     assert(res == sizeof(unsigned long long));
0524 
0525     close(fd1);
0526     close(fd2);
0527 
0528     if (breaks1 != 1 || breaks2 != 1) {
0529         printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);
0530         return 1;
0531     }
0532 
0533     printf("TESTED: %s\n", desc);
0534     return 0;
0535 }
0536 
0537 static int test_syswide_multi_diff_addr(void)
0538 {
0539     unsigned long long breaks1 = 0, breaks2 = 0;
0540     int *fd1 = malloc(nprocs * sizeof(int));
0541     int *fd2 = malloc(nprocs * sizeof(int));
0542     char *desc = "Systemwide, Two events, diff addr";
0543     int ret;
0544 
0545     ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
0546     if (ret) {
0547         perror("perf_systemwide_event_open");
0548         exit(EXIT_FAILURE);
0549     }
0550 
0551     ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_RW, (__u64)&b, (__u64)sizeof(b));
0552     if (ret) {
0553         close_fds(fd1, nprocs);
0554         perror("perf_systemwide_event_open");
0555         exit(EXIT_FAILURE);
0556     }
0557 
0558     reset_fds(fd1, nprocs);
0559     reset_fds(fd2, nprocs);
0560     enable_fds(fd1, nprocs);
0561     enable_fds(fd2, nprocs);
0562     multi_dawr_workload();
0563     disable_fds(fd1, nprocs);
0564     disable_fds(fd2, nprocs);
0565 
0566     breaks1 = read_fds(fd1, nprocs);
0567     breaks2 = read_fds(fd2, nprocs);
0568 
0569     close_fds(fd1, nprocs);
0570     close_fds(fd2, nprocs);
0571 
0572     free(fd1);
0573     free(fd2);
0574 
0575     if (breaks1 != 2 || breaks2 != 2) {
0576         printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);
0577         return 1;
0578     }
0579 
0580     printf("TESTED: %s\n", desc);
0581     return 0;
0582 }
0583 
0584 static int test_syswide_multi_same_addr(void)
0585 {
0586     unsigned long long breaks1 = 0, breaks2 = 0;
0587     int *fd1 = malloc(nprocs * sizeof(int));
0588     int *fd2 = malloc(nprocs * sizeof(int));
0589     char *desc = "Systemwide, Two events, same addr";
0590     int ret;
0591 
0592     ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
0593     if (ret) {
0594         perror("perf_systemwide_event_open");
0595         exit(EXIT_FAILURE);
0596     }
0597 
0598     ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
0599     if (ret) {
0600         close_fds(fd1, nprocs);
0601         perror("perf_systemwide_event_open");
0602         exit(EXIT_FAILURE);
0603     }
0604 
0605     reset_fds(fd1, nprocs);
0606     reset_fds(fd2, nprocs);
0607     enable_fds(fd1, nprocs);
0608     enable_fds(fd2, nprocs);
0609     multi_dawr_workload();
0610     disable_fds(fd1, nprocs);
0611     disable_fds(fd2, nprocs);
0612 
0613     breaks1 = read_fds(fd1, nprocs);
0614     breaks2 = read_fds(fd2, nprocs);
0615 
0616     close_fds(fd1, nprocs);
0617     close_fds(fd2, nprocs);
0618 
0619     free(fd1);
0620     free(fd2);
0621 
0622     if (breaks1 != 2 || breaks2 != 2) {
0623         printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);
0624         return 1;
0625     }
0626 
0627     printf("TESTED: %s\n", desc);
0628     return 0;
0629 }
0630 
0631 static int test_syswide_multi_diff_addr_ro_wo(void)
0632 {
0633     unsigned long long breaks1 = 0, breaks2 = 0;
0634     int *fd1 = malloc(nprocs * sizeof(int));
0635     int *fd2 = malloc(nprocs * sizeof(int));
0636     char *desc = "Systemwide, Two events, diff addr, one is RO, other is WO";
0637     int ret;
0638 
0639     ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));
0640     if (ret) {
0641         perror("perf_systemwide_event_open");
0642         exit(EXIT_FAILURE);
0643     }
0644 
0645     ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_R, (__u64)&b, (__u64)sizeof(b));
0646     if (ret) {
0647         close_fds(fd1, nprocs);
0648         perror("perf_systemwide_event_open");
0649         exit(EXIT_FAILURE);
0650     }
0651 
0652     reset_fds(fd1, nprocs);
0653     reset_fds(fd2, nprocs);
0654     enable_fds(fd1, nprocs);
0655     enable_fds(fd2, nprocs);
0656     multi_dawr_workload();
0657     disable_fds(fd1, nprocs);
0658     disable_fds(fd2, nprocs);
0659 
0660     breaks1 = read_fds(fd1, nprocs);
0661     breaks2 = read_fds(fd2, nprocs);
0662 
0663     close_fds(fd1, nprocs);
0664     close_fds(fd2, nprocs);
0665 
0666     free(fd1);
0667     free(fd2);
0668 
0669     if (breaks1 != 1 || breaks2 != 1) {
0670         printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);
0671         return 1;
0672     }
0673 
0674     printf("TESTED: %s\n", desc);
0675     return 0;
0676 }
0677 
0678 static int test_syswide_multi_same_addr_ro_wo(void)
0679 {
0680     unsigned long long breaks1 = 0, breaks2 = 0;
0681     int *fd1 = malloc(nprocs * sizeof(int));
0682     int *fd2 = malloc(nprocs * sizeof(int));
0683     char *desc = "Systemwide, Two events, same addr, one is RO, other is WO";
0684     int ret;
0685 
0686     ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));
0687     if (ret) {
0688         perror("perf_systemwide_event_open");
0689         exit(EXIT_FAILURE);
0690     }
0691 
0692     ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_R, (__u64)&a, (__u64)sizeof(a));
0693     if (ret) {
0694         close_fds(fd1, nprocs);
0695         perror("perf_systemwide_event_open");
0696         exit(EXIT_FAILURE);
0697     }
0698 
0699     reset_fds(fd1, nprocs);
0700     reset_fds(fd2, nprocs);
0701     enable_fds(fd1, nprocs);
0702     enable_fds(fd2, nprocs);
0703     multi_dawr_workload();
0704     disable_fds(fd1, nprocs);
0705     disable_fds(fd2, nprocs);
0706 
0707     breaks1 = read_fds(fd1, nprocs);
0708     breaks2 = read_fds(fd2, nprocs);
0709 
0710     close_fds(fd1, nprocs);
0711     close_fds(fd2, nprocs);
0712 
0713     free(fd1);
0714     free(fd2);
0715 
0716     if (breaks1 != 1 || breaks2 != 1) {
0717         printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);
0718         return 1;
0719     }
0720 
0721     printf("TESTED: %s\n", desc);
0722     return 0;
0723 }
0724 
0725 static int runtest_multi_dawr(void)
0726 {
0727     int ret = 0;
0728 
0729     ret |= test_process_multi_diff_addr();
0730     ret |= test_process_multi_same_addr();
0731     ret |= test_process_multi_diff_addr_ro_wo();
0732     ret |= test_process_multi_same_addr_ro_wo();
0733     ret |= test_syswide_multi_diff_addr();
0734     ret |= test_syswide_multi_same_addr();
0735     ret |= test_syswide_multi_diff_addr_ro_wo();
0736     ret |= test_syswide_multi_same_addr_ro_wo();
0737 
0738     return ret;
0739 }
0740 
0741 static int runtest_unaligned_512bytes(void)
0742 {
0743     unsigned long long breaks = 0;
0744     int fd;
0745     char *desc = "Process specific, 512 bytes, unaligned";
0746     __u64 addr = (__u64)&c + 8;
0747     size_t res;
0748 
0749     fd = perf_process_event_open(HW_BREAKPOINT_RW, addr, 512);
0750     if (fd < 0) {
0751         perror("perf_process_event_open");
0752         exit(EXIT_FAILURE);
0753     }
0754 
0755     ioctl(fd, PERF_EVENT_IOC_RESET);
0756     ioctl(fd, PERF_EVENT_IOC_ENABLE);
0757     multi_dawr_workload();
0758     ioctl(fd, PERF_EVENT_IOC_DISABLE);
0759 
0760     res = read(fd, &breaks, sizeof(breaks));
0761     assert(res == sizeof(unsigned long long));
0762 
0763     close(fd);
0764 
0765     if (breaks != 2) {
0766         printf("FAILED: %s: %lld != 2\n", desc, breaks);
0767         return 1;
0768     }
0769 
0770     printf("TESTED: %s\n", desc);
0771     return 0;
0772 }
0773 
0774 /* There is no perf api to find number of available watchpoints. Use ptrace. */
0775 static int get_nr_wps(bool *arch_31)
0776 {
0777     struct ppc_debug_info dbginfo;
0778     int child_pid;
0779 
0780     child_pid = fork();
0781     if (!child_pid) {
0782         int ret = ptrace(PTRACE_TRACEME, 0, NULL, 0);
0783         if (ret) {
0784             perror("PTRACE_TRACEME failed\n");
0785             exit(EXIT_FAILURE);
0786         }
0787         kill(getpid(), SIGUSR1);
0788 
0789         sleep(1);
0790         exit(EXIT_SUCCESS);
0791     }
0792 
0793     wait(NULL);
0794     if (ptrace(PPC_PTRACE_GETHWDBGINFO, child_pid, NULL, &dbginfo)) {
0795         perror("Can't get breakpoint info");
0796         exit(EXIT_FAILURE);
0797     }
0798 
0799     *arch_31 = !!(dbginfo.features & PPC_DEBUG_FEATURE_DATA_BP_ARCH_31);
0800     return dbginfo.num_data_bps;
0801 }
0802 
0803 static int runtest(void)
0804 {
0805     int rwflag;
0806     int exclude_user;
0807     int ret;
0808     bool dawr = dawr_supported();
0809     bool arch_31 = false;
0810     int nr_wps = get_nr_wps(&arch_31);
0811 
0812     /*
0813      * perf defines rwflag as two bits read and write and at least
0814      * one must be set.  So range 1-3.
0815      */
0816     for (rwflag = 1 ; rwflag < 4; rwflag++) {
0817         for (exclude_user = 0 ; exclude_user < 2; exclude_user++) {
0818             ret = runtestsingle(rwflag, exclude_user, 0);
0819             if (ret)
0820                 return ret;
0821 
0822             /* if we have the dawr, we can do an array test */
0823             if (!dawr)
0824                 continue;
0825             ret = runtestsingle(rwflag, exclude_user, 1);
0826             if (ret)
0827                 return ret;
0828         }
0829     }
0830 
0831     ret = runtest_dar_outside();
0832     if (ret)
0833         return ret;
0834 
0835     if (dawr && nr_wps > 1) {
0836         nprocs = get_nprocs();
0837         ret = runtest_multi_dawr();
0838         if (ret)
0839             return ret;
0840     }
0841 
0842     if (dawr && arch_31)
0843         ret = runtest_unaligned_512bytes();
0844 
0845     return ret;
0846 }
0847 
0848 
0849 static int perf_hwbreak(void)
0850 {
0851     srand ( time(NULL) );
0852 
0853     SKIP_IF(!perf_breakpoint_supported());
0854 
0855     return runtest();
0856 }
0857 
0858 int main(int argc, char *argv[], char **envp)
0859 {
0860     return test_harness(perf_hwbreak, "perf_hwbreak");
0861 }