linux/tools/testing/selftests/powerpc/ptrace/perf-hwbreak.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * perf events self profiling example test case for hw breakpoints.
   4 *
   5 * This tests perf PERF_TYPE_BREAKPOINT parameters
   6 * 1) tests all variants of the break on read/write flags
   7 * 2) tests exclude_user == 0 and 1
   8 * 3) test array matches (if DAWR is supported))
   9 * 4) test different numbers of breakpoints matches
  10 *
  11 * Configure this breakpoint, then read and write the data a number of
  12 * times. Then check the output count from perf is as expected.
  13 *
  14 * Based on:
  15 *   http://ozlabs.org/~anton/junkcode/perf_events_example1.c
  16 *
  17 * Copyright (C) 2018 Michael Neuling, IBM Corporation.
  18 */
  19
  20#include <unistd.h>
  21#include <assert.h>
  22#include <stdio.h>
  23#include <stdlib.h>
  24#include <signal.h>
  25#include <string.h>
  26#include <sys/ioctl.h>
  27#include <sys/wait.h>
  28#include <sys/ptrace.h>
  29#include <sys/sysinfo.h>
  30#include <asm/ptrace.h>
  31#include <elf.h>
  32#include <pthread.h>
  33#include <sys/syscall.h>
  34#include <linux/perf_event.h>
  35#include <linux/hw_breakpoint.h>
  36#include "utils.h"
  37
  38#ifndef PPC_DEBUG_FEATURE_DATA_BP_ARCH_31
  39#define PPC_DEBUG_FEATURE_DATA_BP_ARCH_31       0x20
  40#endif
  41
  42#define MAX_LOOPS 10000
  43
  44#define DAWR_LENGTH_MAX ((0x3f + 1) * 8)
  45
  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        /* Assume online processors are 0 to nprocs for simplisity */
 146        for (i = 0; i < nprocs; i++) {
 147                fd[i] = perf_cpu_event_open(i, type, addr, len);
 148                if (fd[i] < 0) {
 149                        close_fds(fd, i);
 150                        return fd[i];
 151                }
 152        }
 153        return 0;
 154}
 155
 156static inline bool breakpoint_test(int len)
 157{
 158        int fd;
 159
 160        /* bp_addr can point anywhere but needs to be aligned */
 161        fd = perf_process_event_open(HW_BREAKPOINT_R, (__u64)(&fd) & 0xfffffffffffff800, len);
 162        if (fd < 0)
 163                return false;
 164        close(fd);
 165        return true;
 166}
 167
 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); /* provide some variability */
 189        volatile int *k;
 190        __u64 len;
 191
 192        /* align to 0x400 boundary as required by DAWR */
 193        readintalign = (int *)(((unsigned long)readintarraybig + 0x7ff) &
 194                               0xfffffffffffff800);
 195
 196        ptr = &readint;
 197        if (arraytest)
 198                ptr = &readintalign[0];
 199
 200        len = arraytest ? DAWR_LENGTH_MAX : sizeof(int);
 201        break_fd = perf_process_event_open_exclude_user(readwriteflag, (__u64)ptr,
 202                                                        len, exclude_user);
 203        if (break_fd < 0) {
 204                perror("perf_process_event_open_exclude_user");
 205                exit(1);
 206        }
 207
 208        /* start counters */
 209        ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
 210
 211        /* Test a bunch of reads and writes */
 212        k = &readint;
 213        for (i = 0; i < loop_num; i++) {
 214                if (arraytest)
 215                        k = &(readintalign[i % (DAWR_LENGTH_MAX/sizeof(int))]);
 216
 217                j = *k;
 218                *k = j;
 219        }
 220
 221        /* stop counters */
 222        ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
 223
 224        /* read and check counters */
 225        res = read(break_fd, &breaks, sizeof(unsigned long long));
 226        assert(res == sizeof(unsigned long long));
 227        /* we read and write each loop, so subtract the ones we are counting */
 228        needed = 0;
 229        if (readwriteflag & HW_BREAKPOINT_R)
 230                needed += loop_num;
 231        if (readwriteflag & HW_BREAKPOINT_W)
 232                needed += loop_num;
 233        needed = needed * (1 - exclude_user);
 234        printf("TESTED: addr:0x%lx brks:% 8lld loops:% 8i rw:%i !user:%i array:%i\n",
 235               (unsigned long int)ptr, breaks, loop_num, readwriteflag, exclude_user, arraytest);
 236        if (breaks != needed) {
 237                printf("FAILED: 0x%lx brks:%lld needed:%lli %i %i %i\n\n",
 238                       (unsigned long int)ptr, breaks, needed, loop_num, readwriteflag, exclude_user);
 239                return 1;
 240        }
 241        close(break_fd);
 242
 243        return 0;
 244}
 245
 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        /* watch middle half of target array */
 263        break_fd = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)(target + 2), 4);
 264        if (break_fd < 0) {
 265                free(target);
 266                perror("perf_process_event_open");
 267                exit(EXIT_FAILURE);
 268        }
 269
 270        /* Shouldn't hit. */
 271        ioctl(break_fd, PERF_EVENT_IOC_RESET);
 272        ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
 273        temp16 = *((__u16 *)target);
 274        *((__u16 *)target) = temp16;
 275        ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
 276        res = read(break_fd, &breaks, sizeof(unsigned long long));
 277        assert(res == sizeof(unsigned long long));
 278        if (breaks == 0) {
 279                printf("TESTED: No overlap\n");
 280        } else {
 281                printf("FAILED: No overlap: %lld != 0\n", breaks);
 282                fail = 1;
 283        }
 284
 285        /* Hit */
 286        ioctl(break_fd, PERF_EVENT_IOC_RESET);
 287        ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
 288        temp16 = *((__u16 *)(target + 1));
 289        *((__u16 *)(target + 1)) = temp16;
 290        ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
 291        res = read(break_fd, &breaks, sizeof(unsigned long long));
 292        assert(res == sizeof(unsigned long long));
 293        if (breaks == 2) {
 294                printf("TESTED: Partial overlap\n");
 295        } else {
 296                printf("FAILED: Partial overlap: %lld != 2\n", breaks);
 297                fail = 1;
 298        }
 299
 300        /* Hit */
 301        ioctl(break_fd, PERF_EVENT_IOC_RESET);
 302        ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
 303        temp16 = *((__u16 *)(target + 5));
 304        *((__u16 *)(target + 5)) = temp16;
 305        ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
 306        res = read(break_fd, &breaks, sizeof(unsigned long long));
 307        assert(res == sizeof(unsigned long long));
 308        if (breaks == 2) {
 309                printf("TESTED: Partial overlap\n");
 310        } else {
 311                printf("FAILED: Partial overlap: %lld != 2\n", breaks);
 312                fail = 1;
 313        }
 314
 315        /* Shouldn't Hit */
 316        ioctl(break_fd, PERF_EVENT_IOC_RESET);
 317        ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
 318        temp16 = *((__u16 *)(target + 6));
 319        *((__u16 *)(target + 6)) = temp16;
 320        ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
 321        res = read(break_fd, &breaks, sizeof(unsigned long long));
 322        assert(res == sizeof(unsigned long long));
 323        if (breaks == 0) {
 324                printf("TESTED: No overlap\n");
 325        } else {
 326                printf("FAILED: No overlap: %lld != 0\n", breaks);
 327                fail = 1;
 328        }
 329
 330        /* Hit */
 331        ioctl(break_fd, PERF_EVENT_IOC_RESET);
 332        ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
 333        temp64 = *((__u64 *)target);
 334        *((__u64 *)target) = temp64;
 335        ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
 336        res = read(break_fd, &breaks, sizeof(unsigned long long));
 337        assert(res == sizeof(unsigned long long));
 338        if (breaks == 2) {
 339                printf("TESTED: Full overlap\n");
 340        } else {
 341                printf("FAILED: Full overlap: %lld != 2\n", breaks);
 342                fail = 1;
 343        }
 344
 345        free(target);
 346        close(break_fd);
 347        return fail;
 348}
 349
 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/* There is no perf api to find number of available watchpoints. Use ptrace. */
 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         * perf defines rwflag as two bits read and write and at least
 814         * one must be set.  So range 1-3.
 815         */
 816        for (rwflag = 1 ; rwflag < 4; rwflag++) {
 817                for (exclude_user = 0 ; exclude_user < 2; exclude_user++) {
 818                        ret = runtestsingle(rwflag, exclude_user, 0);
 819                        if (ret)
 820                                return ret;
 821
 822                        /* if we have the dawr, we can do an array test */
 823                        if (!dawr)
 824                                continue;
 825                        ret = runtestsingle(rwflag, exclude_user, 1);
 826                        if (ret)
 827                                return ret;
 828                }
 829        }
 830
 831        ret = runtest_dar_outside();
 832        if (ret)
 833                return ret;
 834
 835        if (dawr && nr_wps > 1) {
 836                nprocs = get_nprocs();
 837                ret = runtest_multi_dawr();
 838                if (ret)
 839                        return ret;
 840        }
 841
 842        if (dawr && arch_31)
 843                ret = runtest_unaligned_512bytes();
 844
 845        return ret;
 846}
 847
 848
 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