0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
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
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
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);
0189 volatile int *k;
0190 __u64 len;
0191
0192
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
0209 ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
0210
0211
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
0222 ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
0223
0224
0225 res = read(break_fd, &breaks, sizeof(unsigned long long));
0226 assert(res == sizeof(unsigned long long));
0227
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
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
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
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
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
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
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
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
0814
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
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 }