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