12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 29c2d72d4SMichael Neuling /* 39c2d72d4SMichael Neuling * perf events self profiling example test case for hw breakpoints. 49c2d72d4SMichael Neuling * 59c2d72d4SMichael Neuling * This tests perf PERF_TYPE_BREAKPOINT parameters 69c2d72d4SMichael Neuling * 1) tests all variants of the break on read/write flags 79c2d72d4SMichael Neuling * 2) tests exclude_user == 0 and 1 89c2d72d4SMichael Neuling * 3) test array matches (if DAWR is supported)) 99c2d72d4SMichael Neuling * 4) test different numbers of breakpoints matches 109c2d72d4SMichael Neuling * 119c2d72d4SMichael Neuling * Configure this breakpoint, then read and write the data a number of 129c2d72d4SMichael Neuling * times. Then check the output count from perf is as expected. 139c2d72d4SMichael Neuling * 149c2d72d4SMichael Neuling * Based on: 159c2d72d4SMichael Neuling * http://ozlabs.org/~anton/junkcode/perf_events_example1.c 169c2d72d4SMichael Neuling * 179c2d72d4SMichael Neuling * Copyright (C) 2018 Michael Neuling, IBM Corporation. 189c2d72d4SMichael Neuling */ 199c2d72d4SMichael Neuling 209c2d72d4SMichael Neuling #include <unistd.h> 219c2d72d4SMichael Neuling #include <assert.h> 229c2d72d4SMichael Neuling #include <stdio.h> 239c2d72d4SMichael Neuling #include <stdlib.h> 24*c65c64ccSRavi Bangoria #include <signal.h> 259c2d72d4SMichael Neuling #include <string.h> 269c2d72d4SMichael Neuling #include <sys/ioctl.h> 27*c65c64ccSRavi Bangoria #include <sys/wait.h> 28*c65c64ccSRavi Bangoria #include <sys/ptrace.h> 29*c65c64ccSRavi Bangoria #include <sys/sysinfo.h> 30*c65c64ccSRavi Bangoria #include <asm/ptrace.h> 319c2d72d4SMichael Neuling #include <elf.h> 329c2d72d4SMichael Neuling #include <pthread.h> 339c2d72d4SMichael Neuling #include <sys/syscall.h> 349c2d72d4SMichael Neuling #include <linux/perf_event.h> 359c2d72d4SMichael Neuling #include <linux/hw_breakpoint.h> 369c2d72d4SMichael Neuling #include "utils.h" 379c2d72d4SMichael Neuling 38dae4ff80SRavi Bangoria #ifndef PPC_DEBUG_FEATURE_DATA_BP_ARCH_31 39dae4ff80SRavi Bangoria #define PPC_DEBUG_FEATURE_DATA_BP_ARCH_31 0x20 40dae4ff80SRavi Bangoria #endif 41dae4ff80SRavi Bangoria 429c2d72d4SMichael Neuling #define MAX_LOOPS 10000 439c2d72d4SMichael Neuling 449c2d72d4SMichael Neuling #define DAWR_LENGTH_MAX ((0x3f + 1) * 8) 459c2d72d4SMichael Neuling 46*c65c64ccSRavi Bangoria int nprocs; 47*c65c64ccSRavi Bangoria 48*c65c64ccSRavi Bangoria static volatile int a = 10; 49*c65c64ccSRavi Bangoria static volatile int b = 10; 50*c65c64ccSRavi Bangoria static volatile char c[512 + 8] __attribute__((aligned(512))); 51*c65c64ccSRavi Bangoria 52c9cb0afbSRavi Bangoria static void perf_event_attr_set(struct perf_event_attr *attr, 53c9cb0afbSRavi Bangoria __u32 type, __u64 addr, __u64 len, 54c9cb0afbSRavi Bangoria bool exclude_user) 559c2d72d4SMichael Neuling { 56c9cb0afbSRavi Bangoria memset(attr, 0, sizeof(struct perf_event_attr)); 57c9cb0afbSRavi Bangoria attr->type = PERF_TYPE_BREAKPOINT; 58c9cb0afbSRavi Bangoria attr->size = sizeof(struct perf_event_attr); 59c9cb0afbSRavi Bangoria attr->bp_type = type; 60c9cb0afbSRavi Bangoria attr->bp_addr = addr; 61c9cb0afbSRavi Bangoria attr->bp_len = len; 62c9cb0afbSRavi Bangoria attr->exclude_kernel = 1; 63c9cb0afbSRavi Bangoria attr->exclude_hv = 1; 64c9cb0afbSRavi Bangoria attr->exclude_guest = 1; 65c9cb0afbSRavi Bangoria attr->exclude_user = exclude_user; 66c9cb0afbSRavi Bangoria attr->disabled = 1; 67c9cb0afbSRavi Bangoria } 68c9cb0afbSRavi Bangoria 69c9cb0afbSRavi Bangoria static int 70c9cb0afbSRavi Bangoria perf_process_event_open_exclude_user(__u32 type, __u64 addr, __u64 len, bool exclude_user) 71c9cb0afbSRavi Bangoria { 72c9cb0afbSRavi Bangoria struct perf_event_attr attr; 73c9cb0afbSRavi Bangoria 74c9cb0afbSRavi Bangoria perf_event_attr_set(&attr, type, addr, len, exclude_user); 75c9cb0afbSRavi Bangoria return syscall(__NR_perf_event_open, &attr, getpid(), -1, -1, 0); 76c9cb0afbSRavi Bangoria } 77c9cb0afbSRavi Bangoria 78c9cb0afbSRavi Bangoria static int perf_process_event_open(__u32 type, __u64 addr, __u64 len) 79c9cb0afbSRavi Bangoria { 80c9cb0afbSRavi Bangoria struct perf_event_attr attr; 81c9cb0afbSRavi Bangoria 82c9cb0afbSRavi Bangoria perf_event_attr_set(&attr, type, addr, len, 0); 83c9cb0afbSRavi Bangoria return syscall(__NR_perf_event_open, &attr, getpid(), -1, -1, 0); 849c2d72d4SMichael Neuling } 859c2d72d4SMichael Neuling 86*c65c64ccSRavi Bangoria static int perf_cpu_event_open(long cpu, __u32 type, __u64 addr, __u64 len) 87*c65c64ccSRavi Bangoria { 88*c65c64ccSRavi Bangoria struct perf_event_attr attr; 89*c65c64ccSRavi Bangoria 90*c65c64ccSRavi Bangoria perf_event_attr_set(&attr, type, addr, len, 0); 91*c65c64ccSRavi Bangoria return syscall(__NR_perf_event_open, &attr, -1, cpu, -1, 0); 92*c65c64ccSRavi Bangoria } 93*c65c64ccSRavi Bangoria 94*c65c64ccSRavi Bangoria static void close_fds(int *fd, int n) 95*c65c64ccSRavi Bangoria { 96*c65c64ccSRavi Bangoria int i; 97*c65c64ccSRavi Bangoria 98*c65c64ccSRavi Bangoria for (i = 0; i < n; i++) 99*c65c64ccSRavi Bangoria close(fd[i]); 100*c65c64ccSRavi Bangoria } 101*c65c64ccSRavi Bangoria 102*c65c64ccSRavi Bangoria static unsigned long read_fds(int *fd, int n) 103*c65c64ccSRavi Bangoria { 104*c65c64ccSRavi Bangoria int i; 105*c65c64ccSRavi Bangoria unsigned long c = 0; 106*c65c64ccSRavi Bangoria unsigned long count = 0; 107*c65c64ccSRavi Bangoria size_t res; 108*c65c64ccSRavi Bangoria 109*c65c64ccSRavi Bangoria for (i = 0; i < n; i++) { 110*c65c64ccSRavi Bangoria res = read(fd[i], &c, sizeof(c)); 111*c65c64ccSRavi Bangoria assert(res == sizeof(unsigned long long)); 112*c65c64ccSRavi Bangoria count += c; 113*c65c64ccSRavi Bangoria } 114*c65c64ccSRavi Bangoria return count; 115*c65c64ccSRavi Bangoria } 116*c65c64ccSRavi Bangoria 117*c65c64ccSRavi Bangoria static void reset_fds(int *fd, int n) 118*c65c64ccSRavi Bangoria { 119*c65c64ccSRavi Bangoria int i; 120*c65c64ccSRavi Bangoria 121*c65c64ccSRavi Bangoria for (i = 0; i < n; i++) 122*c65c64ccSRavi Bangoria ioctl(fd[i], PERF_EVENT_IOC_RESET); 123*c65c64ccSRavi Bangoria } 124*c65c64ccSRavi Bangoria 125*c65c64ccSRavi Bangoria static void enable_fds(int *fd, int n) 126*c65c64ccSRavi Bangoria { 127*c65c64ccSRavi Bangoria int i; 128*c65c64ccSRavi Bangoria 129*c65c64ccSRavi Bangoria for (i = 0; i < n; i++) 130*c65c64ccSRavi Bangoria ioctl(fd[i], PERF_EVENT_IOC_ENABLE); 131*c65c64ccSRavi Bangoria } 132*c65c64ccSRavi Bangoria 133*c65c64ccSRavi Bangoria static void disable_fds(int *fd, int n) 134*c65c64ccSRavi Bangoria { 135*c65c64ccSRavi Bangoria int i; 136*c65c64ccSRavi Bangoria 137*c65c64ccSRavi Bangoria for (i = 0; i < n; i++) 138*c65c64ccSRavi Bangoria ioctl(fd[i], PERF_EVENT_IOC_DISABLE); 139*c65c64ccSRavi Bangoria } 140*c65c64ccSRavi Bangoria 141*c65c64ccSRavi Bangoria static int perf_systemwide_event_open(int *fd, __u32 type, __u64 addr, __u64 len) 142*c65c64ccSRavi Bangoria { 143*c65c64ccSRavi Bangoria int i = 0; 144*c65c64ccSRavi Bangoria 145*c65c64ccSRavi Bangoria /* Assume online processors are 0 to nprocs for simplisity */ 146*c65c64ccSRavi Bangoria for (i = 0; i < nprocs; i++) { 147*c65c64ccSRavi Bangoria fd[i] = perf_cpu_event_open(i, type, addr, len); 148*c65c64ccSRavi Bangoria if (fd[i] < 0) { 149*c65c64ccSRavi Bangoria close_fds(fd, i); 150*c65c64ccSRavi Bangoria return fd[i]; 151*c65c64ccSRavi Bangoria } 152*c65c64ccSRavi Bangoria } 153*c65c64ccSRavi Bangoria return 0; 154*c65c64ccSRavi Bangoria } 155*c65c64ccSRavi Bangoria 1569c2d72d4SMichael Neuling static inline bool breakpoint_test(int len) 1579c2d72d4SMichael Neuling { 1589c2d72d4SMichael Neuling int fd; 1599c2d72d4SMichael Neuling 1609c2d72d4SMichael Neuling /* bp_addr can point anywhere but needs to be aligned */ 161c9cb0afbSRavi Bangoria fd = perf_process_event_open(HW_BREAKPOINT_R, (__u64)(&fd) & 0xfffffffffffff800, len); 1629c2d72d4SMichael Neuling if (fd < 0) 1639c2d72d4SMichael Neuling return false; 1649c2d72d4SMichael Neuling close(fd); 1659c2d72d4SMichael Neuling return true; 1669c2d72d4SMichael Neuling } 1679c2d72d4SMichael Neuling 1689c2d72d4SMichael Neuling static inline bool perf_breakpoint_supported(void) 1699c2d72d4SMichael Neuling { 1709c2d72d4SMichael Neuling return breakpoint_test(4); 1719c2d72d4SMichael Neuling } 1729c2d72d4SMichael Neuling 1739c2d72d4SMichael Neuling static inline bool dawr_supported(void) 1749c2d72d4SMichael Neuling { 1759c2d72d4SMichael Neuling return breakpoint_test(DAWR_LENGTH_MAX); 1769c2d72d4SMichael Neuling } 1779c2d72d4SMichael Neuling 1789c2d72d4SMichael Neuling static int runtestsingle(int readwriteflag, int exclude_user, int arraytest) 1799c2d72d4SMichael Neuling { 1809c2d72d4SMichael Neuling int i,j; 1819c2d72d4SMichael Neuling size_t res; 1829c2d72d4SMichael Neuling unsigned long long breaks, needed; 1839c2d72d4SMichael Neuling int readint; 1849c2d72d4SMichael Neuling int readintarraybig[2*DAWR_LENGTH_MAX/sizeof(int)]; 1859c2d72d4SMichael Neuling int *readintalign; 1869c2d72d4SMichael Neuling volatile int *ptr; 1879c2d72d4SMichael Neuling int break_fd; 1889c2d72d4SMichael Neuling int loop_num = MAX_LOOPS - (rand() % 100); /* provide some variability */ 1899c2d72d4SMichael Neuling volatile int *k; 190c9cb0afbSRavi Bangoria __u64 len; 1919c2d72d4SMichael Neuling 1929c2d72d4SMichael Neuling /* align to 0x400 boundary as required by DAWR */ 1939c2d72d4SMichael Neuling readintalign = (int *)(((unsigned long)readintarraybig + 0x7ff) & 1949c2d72d4SMichael Neuling 0xfffffffffffff800); 1959c2d72d4SMichael Neuling 1969c2d72d4SMichael Neuling ptr = &readint; 1979c2d72d4SMichael Neuling if (arraytest) 1989c2d72d4SMichael Neuling ptr = &readintalign[0]; 1999c2d72d4SMichael Neuling 200c9cb0afbSRavi Bangoria len = arraytest ? DAWR_LENGTH_MAX : sizeof(int); 201c9cb0afbSRavi Bangoria break_fd = perf_process_event_open_exclude_user(readwriteflag, (__u64)ptr, 202c9cb0afbSRavi Bangoria len, exclude_user); 2039c2d72d4SMichael Neuling if (break_fd < 0) { 204c9cb0afbSRavi Bangoria perror("perf_process_event_open_exclude_user"); 2059c2d72d4SMichael Neuling exit(1); 2069c2d72d4SMichael Neuling } 2079c2d72d4SMichael Neuling 2089c2d72d4SMichael Neuling /* start counters */ 2099c2d72d4SMichael Neuling ioctl(break_fd, PERF_EVENT_IOC_ENABLE); 2109c2d72d4SMichael Neuling 2119c2d72d4SMichael Neuling /* Test a bunch of reads and writes */ 2129c2d72d4SMichael Neuling k = &readint; 2139c2d72d4SMichael Neuling for (i = 0; i < loop_num; i++) { 2149c2d72d4SMichael Neuling if (arraytest) 2159c2d72d4SMichael Neuling k = &(readintalign[i % (DAWR_LENGTH_MAX/sizeof(int))]); 2169c2d72d4SMichael Neuling 2179c2d72d4SMichael Neuling j = *k; 2189c2d72d4SMichael Neuling *k = j; 2199c2d72d4SMichael Neuling } 2209c2d72d4SMichael Neuling 2219c2d72d4SMichael Neuling /* stop counters */ 2229c2d72d4SMichael Neuling ioctl(break_fd, PERF_EVENT_IOC_DISABLE); 2239c2d72d4SMichael Neuling 2249c2d72d4SMichael Neuling /* read and check counters */ 2259c2d72d4SMichael Neuling res = read(break_fd, &breaks, sizeof(unsigned long long)); 2269c2d72d4SMichael Neuling assert(res == sizeof(unsigned long long)); 2279c2d72d4SMichael Neuling /* we read and write each loop, so subtract the ones we are counting */ 2289c2d72d4SMichael Neuling needed = 0; 2299c2d72d4SMichael Neuling if (readwriteflag & HW_BREAKPOINT_R) 2309c2d72d4SMichael Neuling needed += loop_num; 2319c2d72d4SMichael Neuling if (readwriteflag & HW_BREAKPOINT_W) 2329c2d72d4SMichael Neuling needed += loop_num; 2339c2d72d4SMichael Neuling needed = needed * (1 - exclude_user); 2349c2d72d4SMichael Neuling printf("TESTED: addr:0x%lx brks:% 8lld loops:% 8i rw:%i !user:%i array:%i\n", 2359c2d72d4SMichael Neuling (unsigned long int)ptr, breaks, loop_num, readwriteflag, exclude_user, arraytest); 2369c2d72d4SMichael Neuling if (breaks != needed) { 2379c2d72d4SMichael Neuling printf("FAILED: 0x%lx brks:%lld needed:%lli %i %i %i\n\n", 2389c2d72d4SMichael Neuling (unsigned long int)ptr, breaks, needed, loop_num, readwriteflag, exclude_user); 2399c2d72d4SMichael Neuling return 1; 2409c2d72d4SMichael Neuling } 2419c2d72d4SMichael Neuling close(break_fd); 2429c2d72d4SMichael Neuling 2439c2d72d4SMichael Neuling return 0; 2449c2d72d4SMichael Neuling } 2459c2d72d4SMichael Neuling 246949758a2SRavi Bangoria static int runtest_dar_outside(void) 247949758a2SRavi Bangoria { 248949758a2SRavi Bangoria void *target; 249949758a2SRavi Bangoria volatile __u16 temp16; 250949758a2SRavi Bangoria volatile __u64 temp64; 251949758a2SRavi Bangoria int break_fd; 252949758a2SRavi Bangoria unsigned long long breaks; 253949758a2SRavi Bangoria int fail = 0; 254949758a2SRavi Bangoria size_t res; 255949758a2SRavi Bangoria 256949758a2SRavi Bangoria target = malloc(8); 257949758a2SRavi Bangoria if (!target) { 258949758a2SRavi Bangoria perror("malloc failed"); 259949758a2SRavi Bangoria exit(EXIT_FAILURE); 260949758a2SRavi Bangoria } 261949758a2SRavi Bangoria 262949758a2SRavi Bangoria /* watch middle half of target array */ 263c9cb0afbSRavi Bangoria break_fd = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)(target + 2), 4); 264949758a2SRavi Bangoria if (break_fd < 0) { 265949758a2SRavi Bangoria free(target); 266c9cb0afbSRavi Bangoria perror("perf_process_event_open"); 267949758a2SRavi Bangoria exit(EXIT_FAILURE); 268949758a2SRavi Bangoria } 269949758a2SRavi Bangoria 270949758a2SRavi Bangoria /* Shouldn't hit. */ 271949758a2SRavi Bangoria ioctl(break_fd, PERF_EVENT_IOC_RESET); 272949758a2SRavi Bangoria ioctl(break_fd, PERF_EVENT_IOC_ENABLE); 273949758a2SRavi Bangoria temp16 = *((__u16 *)target); 274949758a2SRavi Bangoria *((__u16 *)target) = temp16; 275949758a2SRavi Bangoria ioctl(break_fd, PERF_EVENT_IOC_DISABLE); 276949758a2SRavi Bangoria res = read(break_fd, &breaks, sizeof(unsigned long long)); 277949758a2SRavi Bangoria assert(res == sizeof(unsigned long long)); 278949758a2SRavi Bangoria if (breaks == 0) { 279949758a2SRavi Bangoria printf("TESTED: No overlap\n"); 280949758a2SRavi Bangoria } else { 281949758a2SRavi Bangoria printf("FAILED: No overlap: %lld != 0\n", breaks); 282949758a2SRavi Bangoria fail = 1; 283949758a2SRavi Bangoria } 284949758a2SRavi Bangoria 285949758a2SRavi Bangoria /* Hit */ 286949758a2SRavi Bangoria ioctl(break_fd, PERF_EVENT_IOC_RESET); 287949758a2SRavi Bangoria ioctl(break_fd, PERF_EVENT_IOC_ENABLE); 288949758a2SRavi Bangoria temp16 = *((__u16 *)(target + 1)); 289949758a2SRavi Bangoria *((__u16 *)(target + 1)) = temp16; 290949758a2SRavi Bangoria ioctl(break_fd, PERF_EVENT_IOC_DISABLE); 291949758a2SRavi Bangoria res = read(break_fd, &breaks, sizeof(unsigned long long)); 292949758a2SRavi Bangoria assert(res == sizeof(unsigned long long)); 293949758a2SRavi Bangoria if (breaks == 2) { 294949758a2SRavi Bangoria printf("TESTED: Partial overlap\n"); 295949758a2SRavi Bangoria } else { 296949758a2SRavi Bangoria printf("FAILED: Partial overlap: %lld != 2\n", breaks); 297949758a2SRavi Bangoria fail = 1; 298949758a2SRavi Bangoria } 299949758a2SRavi Bangoria 300949758a2SRavi Bangoria /* Hit */ 301949758a2SRavi Bangoria ioctl(break_fd, PERF_EVENT_IOC_RESET); 302949758a2SRavi Bangoria ioctl(break_fd, PERF_EVENT_IOC_ENABLE); 303949758a2SRavi Bangoria temp16 = *((__u16 *)(target + 5)); 304949758a2SRavi Bangoria *((__u16 *)(target + 5)) = temp16; 305949758a2SRavi Bangoria ioctl(break_fd, PERF_EVENT_IOC_DISABLE); 306949758a2SRavi Bangoria res = read(break_fd, &breaks, sizeof(unsigned long long)); 307949758a2SRavi Bangoria assert(res == sizeof(unsigned long long)); 308949758a2SRavi Bangoria if (breaks == 2) { 309949758a2SRavi Bangoria printf("TESTED: Partial overlap\n"); 310949758a2SRavi Bangoria } else { 311949758a2SRavi Bangoria printf("FAILED: Partial overlap: %lld != 2\n", breaks); 312949758a2SRavi Bangoria fail = 1; 313949758a2SRavi Bangoria } 314949758a2SRavi Bangoria 315949758a2SRavi Bangoria /* Shouldn't Hit */ 316949758a2SRavi Bangoria ioctl(break_fd, PERF_EVENT_IOC_RESET); 317949758a2SRavi Bangoria ioctl(break_fd, PERF_EVENT_IOC_ENABLE); 318949758a2SRavi Bangoria temp16 = *((__u16 *)(target + 6)); 319949758a2SRavi Bangoria *((__u16 *)(target + 6)) = temp16; 320949758a2SRavi Bangoria ioctl(break_fd, PERF_EVENT_IOC_DISABLE); 321949758a2SRavi Bangoria res = read(break_fd, &breaks, sizeof(unsigned long long)); 322949758a2SRavi Bangoria assert(res == sizeof(unsigned long long)); 323949758a2SRavi Bangoria if (breaks == 0) { 324949758a2SRavi Bangoria printf("TESTED: No overlap\n"); 325949758a2SRavi Bangoria } else { 326949758a2SRavi Bangoria printf("FAILED: No overlap: %lld != 0\n", breaks); 327949758a2SRavi Bangoria fail = 1; 328949758a2SRavi Bangoria } 329949758a2SRavi Bangoria 330949758a2SRavi Bangoria /* Hit */ 331949758a2SRavi Bangoria ioctl(break_fd, PERF_EVENT_IOC_RESET); 332949758a2SRavi Bangoria ioctl(break_fd, PERF_EVENT_IOC_ENABLE); 333949758a2SRavi Bangoria temp64 = *((__u64 *)target); 334949758a2SRavi Bangoria *((__u64 *)target) = temp64; 335949758a2SRavi Bangoria ioctl(break_fd, PERF_EVENT_IOC_DISABLE); 336949758a2SRavi Bangoria res = read(break_fd, &breaks, sizeof(unsigned long long)); 337949758a2SRavi Bangoria assert(res == sizeof(unsigned long long)); 338949758a2SRavi Bangoria if (breaks == 2) { 339949758a2SRavi Bangoria printf("TESTED: Full overlap\n"); 340949758a2SRavi Bangoria } else { 341949758a2SRavi Bangoria printf("FAILED: Full overlap: %lld != 2\n", breaks); 342949758a2SRavi Bangoria fail = 1; 343949758a2SRavi Bangoria } 344949758a2SRavi Bangoria 345949758a2SRavi Bangoria free(target); 346949758a2SRavi Bangoria close(break_fd); 347949758a2SRavi Bangoria return fail; 348949758a2SRavi Bangoria } 349949758a2SRavi Bangoria 350*c65c64ccSRavi Bangoria static void multi_dawr_workload(void) 351*c65c64ccSRavi Bangoria { 352*c65c64ccSRavi Bangoria a += 10; 353*c65c64ccSRavi Bangoria b += 10; 354*c65c64ccSRavi Bangoria c[512 + 1] += 'a'; 355*c65c64ccSRavi Bangoria } 356*c65c64ccSRavi Bangoria 357*c65c64ccSRavi Bangoria static int test_process_multi_diff_addr(void) 358*c65c64ccSRavi Bangoria { 359*c65c64ccSRavi Bangoria unsigned long long breaks1 = 0, breaks2 = 0; 360*c65c64ccSRavi Bangoria int fd1, fd2; 361*c65c64ccSRavi Bangoria char *desc = "Process specific, Two events, diff addr"; 362*c65c64ccSRavi Bangoria size_t res; 363*c65c64ccSRavi Bangoria 364*c65c64ccSRavi Bangoria fd1 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a)); 365*c65c64ccSRavi Bangoria if (fd1 < 0) { 366*c65c64ccSRavi Bangoria perror("perf_process_event_open"); 367*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 368*c65c64ccSRavi Bangoria } 369*c65c64ccSRavi Bangoria 370*c65c64ccSRavi Bangoria fd2 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&b, (__u64)sizeof(b)); 371*c65c64ccSRavi Bangoria if (fd2 < 0) { 372*c65c64ccSRavi Bangoria close(fd1); 373*c65c64ccSRavi Bangoria perror("perf_process_event_open"); 374*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 375*c65c64ccSRavi Bangoria } 376*c65c64ccSRavi Bangoria 377*c65c64ccSRavi Bangoria ioctl(fd1, PERF_EVENT_IOC_RESET); 378*c65c64ccSRavi Bangoria ioctl(fd2, PERF_EVENT_IOC_RESET); 379*c65c64ccSRavi Bangoria ioctl(fd1, PERF_EVENT_IOC_ENABLE); 380*c65c64ccSRavi Bangoria ioctl(fd2, PERF_EVENT_IOC_ENABLE); 381*c65c64ccSRavi Bangoria multi_dawr_workload(); 382*c65c64ccSRavi Bangoria ioctl(fd1, PERF_EVENT_IOC_DISABLE); 383*c65c64ccSRavi Bangoria ioctl(fd2, PERF_EVENT_IOC_DISABLE); 384*c65c64ccSRavi Bangoria 385*c65c64ccSRavi Bangoria res = read(fd1, &breaks1, sizeof(breaks1)); 386*c65c64ccSRavi Bangoria assert(res == sizeof(unsigned long long)); 387*c65c64ccSRavi Bangoria res = read(fd2, &breaks2, sizeof(breaks2)); 388*c65c64ccSRavi Bangoria assert(res == sizeof(unsigned long long)); 389*c65c64ccSRavi Bangoria 390*c65c64ccSRavi Bangoria close(fd1); 391*c65c64ccSRavi Bangoria close(fd2); 392*c65c64ccSRavi Bangoria 393*c65c64ccSRavi Bangoria if (breaks1 != 2 || breaks2 != 2) { 394*c65c64ccSRavi Bangoria printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2); 395*c65c64ccSRavi Bangoria return 1; 396*c65c64ccSRavi Bangoria } 397*c65c64ccSRavi Bangoria 398*c65c64ccSRavi Bangoria printf("TESTED: %s\n", desc); 399*c65c64ccSRavi Bangoria return 0; 400*c65c64ccSRavi Bangoria } 401*c65c64ccSRavi Bangoria 402*c65c64ccSRavi Bangoria static int test_process_multi_same_addr(void) 403*c65c64ccSRavi Bangoria { 404*c65c64ccSRavi Bangoria unsigned long long breaks1 = 0, breaks2 = 0; 405*c65c64ccSRavi Bangoria int fd1, fd2; 406*c65c64ccSRavi Bangoria char *desc = "Process specific, Two events, same addr"; 407*c65c64ccSRavi Bangoria size_t res; 408*c65c64ccSRavi Bangoria 409*c65c64ccSRavi Bangoria fd1 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a)); 410*c65c64ccSRavi Bangoria if (fd1 < 0) { 411*c65c64ccSRavi Bangoria perror("perf_process_event_open"); 412*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 413*c65c64ccSRavi Bangoria } 414*c65c64ccSRavi Bangoria 415*c65c64ccSRavi Bangoria fd2 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a)); 416*c65c64ccSRavi Bangoria if (fd2 < 0) { 417*c65c64ccSRavi Bangoria close(fd1); 418*c65c64ccSRavi Bangoria perror("perf_process_event_open"); 419*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 420*c65c64ccSRavi Bangoria } 421*c65c64ccSRavi Bangoria 422*c65c64ccSRavi Bangoria ioctl(fd1, PERF_EVENT_IOC_RESET); 423*c65c64ccSRavi Bangoria ioctl(fd2, PERF_EVENT_IOC_RESET); 424*c65c64ccSRavi Bangoria ioctl(fd1, PERF_EVENT_IOC_ENABLE); 425*c65c64ccSRavi Bangoria ioctl(fd2, PERF_EVENT_IOC_ENABLE); 426*c65c64ccSRavi Bangoria multi_dawr_workload(); 427*c65c64ccSRavi Bangoria ioctl(fd1, PERF_EVENT_IOC_DISABLE); 428*c65c64ccSRavi Bangoria ioctl(fd2, PERF_EVENT_IOC_DISABLE); 429*c65c64ccSRavi Bangoria 430*c65c64ccSRavi Bangoria res = read(fd1, &breaks1, sizeof(breaks1)); 431*c65c64ccSRavi Bangoria assert(res == sizeof(unsigned long long)); 432*c65c64ccSRavi Bangoria res = read(fd2, &breaks2, sizeof(breaks2)); 433*c65c64ccSRavi Bangoria assert(res == sizeof(unsigned long long)); 434*c65c64ccSRavi Bangoria 435*c65c64ccSRavi Bangoria close(fd1); 436*c65c64ccSRavi Bangoria close(fd2); 437*c65c64ccSRavi Bangoria 438*c65c64ccSRavi Bangoria if (breaks1 != 2 || breaks2 != 2) { 439*c65c64ccSRavi Bangoria printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2); 440*c65c64ccSRavi Bangoria return 1; 441*c65c64ccSRavi Bangoria } 442*c65c64ccSRavi Bangoria 443*c65c64ccSRavi Bangoria printf("TESTED: %s\n", desc); 444*c65c64ccSRavi Bangoria return 0; 445*c65c64ccSRavi Bangoria } 446*c65c64ccSRavi Bangoria 447*c65c64ccSRavi Bangoria static int test_process_multi_diff_addr_ro_wo(void) 448*c65c64ccSRavi Bangoria { 449*c65c64ccSRavi Bangoria unsigned long long breaks1 = 0, breaks2 = 0; 450*c65c64ccSRavi Bangoria int fd1, fd2; 451*c65c64ccSRavi Bangoria char *desc = "Process specific, Two events, diff addr, one is RO, other is WO"; 452*c65c64ccSRavi Bangoria size_t res; 453*c65c64ccSRavi Bangoria 454*c65c64ccSRavi Bangoria fd1 = perf_process_event_open(HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a)); 455*c65c64ccSRavi Bangoria if (fd1 < 0) { 456*c65c64ccSRavi Bangoria perror("perf_process_event_open"); 457*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 458*c65c64ccSRavi Bangoria } 459*c65c64ccSRavi Bangoria 460*c65c64ccSRavi Bangoria fd2 = perf_process_event_open(HW_BREAKPOINT_R, (__u64)&b, (__u64)sizeof(b)); 461*c65c64ccSRavi Bangoria if (fd2 < 0) { 462*c65c64ccSRavi Bangoria close(fd1); 463*c65c64ccSRavi Bangoria perror("perf_process_event_open"); 464*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 465*c65c64ccSRavi Bangoria } 466*c65c64ccSRavi Bangoria 467*c65c64ccSRavi Bangoria ioctl(fd1, PERF_EVENT_IOC_RESET); 468*c65c64ccSRavi Bangoria ioctl(fd2, PERF_EVENT_IOC_RESET); 469*c65c64ccSRavi Bangoria ioctl(fd1, PERF_EVENT_IOC_ENABLE); 470*c65c64ccSRavi Bangoria ioctl(fd2, PERF_EVENT_IOC_ENABLE); 471*c65c64ccSRavi Bangoria multi_dawr_workload(); 472*c65c64ccSRavi Bangoria ioctl(fd1, PERF_EVENT_IOC_DISABLE); 473*c65c64ccSRavi Bangoria ioctl(fd2, PERF_EVENT_IOC_DISABLE); 474*c65c64ccSRavi Bangoria 475*c65c64ccSRavi Bangoria res = read(fd1, &breaks1, sizeof(breaks1)); 476*c65c64ccSRavi Bangoria assert(res == sizeof(unsigned long long)); 477*c65c64ccSRavi Bangoria res = read(fd2, &breaks2, sizeof(breaks2)); 478*c65c64ccSRavi Bangoria assert(res == sizeof(unsigned long long)); 479*c65c64ccSRavi Bangoria 480*c65c64ccSRavi Bangoria close(fd1); 481*c65c64ccSRavi Bangoria close(fd2); 482*c65c64ccSRavi Bangoria 483*c65c64ccSRavi Bangoria if (breaks1 != 1 || breaks2 != 1) { 484*c65c64ccSRavi Bangoria printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2); 485*c65c64ccSRavi Bangoria return 1; 486*c65c64ccSRavi Bangoria } 487*c65c64ccSRavi Bangoria 488*c65c64ccSRavi Bangoria printf("TESTED: %s\n", desc); 489*c65c64ccSRavi Bangoria return 0; 490*c65c64ccSRavi Bangoria } 491*c65c64ccSRavi Bangoria 492*c65c64ccSRavi Bangoria static int test_process_multi_same_addr_ro_wo(void) 493*c65c64ccSRavi Bangoria { 494*c65c64ccSRavi Bangoria unsigned long long breaks1 = 0, breaks2 = 0; 495*c65c64ccSRavi Bangoria int fd1, fd2; 496*c65c64ccSRavi Bangoria char *desc = "Process specific, Two events, same addr, one is RO, other is WO"; 497*c65c64ccSRavi Bangoria size_t res; 498*c65c64ccSRavi Bangoria 499*c65c64ccSRavi Bangoria fd1 = perf_process_event_open(HW_BREAKPOINT_R, (__u64)&a, (__u64)sizeof(a)); 500*c65c64ccSRavi Bangoria if (fd1 < 0) { 501*c65c64ccSRavi Bangoria perror("perf_process_event_open"); 502*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 503*c65c64ccSRavi Bangoria } 504*c65c64ccSRavi Bangoria 505*c65c64ccSRavi Bangoria fd2 = perf_process_event_open(HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a)); 506*c65c64ccSRavi Bangoria if (fd2 < 0) { 507*c65c64ccSRavi Bangoria close(fd1); 508*c65c64ccSRavi Bangoria perror("perf_process_event_open"); 509*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 510*c65c64ccSRavi Bangoria } 511*c65c64ccSRavi Bangoria 512*c65c64ccSRavi Bangoria ioctl(fd1, PERF_EVENT_IOC_RESET); 513*c65c64ccSRavi Bangoria ioctl(fd2, PERF_EVENT_IOC_RESET); 514*c65c64ccSRavi Bangoria ioctl(fd1, PERF_EVENT_IOC_ENABLE); 515*c65c64ccSRavi Bangoria ioctl(fd2, PERF_EVENT_IOC_ENABLE); 516*c65c64ccSRavi Bangoria multi_dawr_workload(); 517*c65c64ccSRavi Bangoria ioctl(fd1, PERF_EVENT_IOC_DISABLE); 518*c65c64ccSRavi Bangoria ioctl(fd2, PERF_EVENT_IOC_DISABLE); 519*c65c64ccSRavi Bangoria 520*c65c64ccSRavi Bangoria res = read(fd1, &breaks1, sizeof(breaks1)); 521*c65c64ccSRavi Bangoria assert(res == sizeof(unsigned long long)); 522*c65c64ccSRavi Bangoria res = read(fd2, &breaks2, sizeof(breaks2)); 523*c65c64ccSRavi Bangoria assert(res == sizeof(unsigned long long)); 524*c65c64ccSRavi Bangoria 525*c65c64ccSRavi Bangoria close(fd1); 526*c65c64ccSRavi Bangoria close(fd2); 527*c65c64ccSRavi Bangoria 528*c65c64ccSRavi Bangoria if (breaks1 != 1 || breaks2 != 1) { 529*c65c64ccSRavi Bangoria printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2); 530*c65c64ccSRavi Bangoria return 1; 531*c65c64ccSRavi Bangoria } 532*c65c64ccSRavi Bangoria 533*c65c64ccSRavi Bangoria printf("TESTED: %s\n", desc); 534*c65c64ccSRavi Bangoria return 0; 535*c65c64ccSRavi Bangoria } 536*c65c64ccSRavi Bangoria 537*c65c64ccSRavi Bangoria static int test_syswide_multi_diff_addr(void) 538*c65c64ccSRavi Bangoria { 539*c65c64ccSRavi Bangoria unsigned long long breaks1 = 0, breaks2 = 0; 540*c65c64ccSRavi Bangoria int *fd1 = malloc(nprocs * sizeof(int)); 541*c65c64ccSRavi Bangoria int *fd2 = malloc(nprocs * sizeof(int)); 542*c65c64ccSRavi Bangoria char *desc = "Systemwide, Two events, diff addr"; 543*c65c64ccSRavi Bangoria int ret; 544*c65c64ccSRavi Bangoria 545*c65c64ccSRavi Bangoria ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a)); 546*c65c64ccSRavi Bangoria if (ret) { 547*c65c64ccSRavi Bangoria perror("perf_systemwide_event_open"); 548*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 549*c65c64ccSRavi Bangoria } 550*c65c64ccSRavi Bangoria 551*c65c64ccSRavi Bangoria ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_RW, (__u64)&b, (__u64)sizeof(b)); 552*c65c64ccSRavi Bangoria if (ret) { 553*c65c64ccSRavi Bangoria close_fds(fd1, nprocs); 554*c65c64ccSRavi Bangoria perror("perf_systemwide_event_open"); 555*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 556*c65c64ccSRavi Bangoria } 557*c65c64ccSRavi Bangoria 558*c65c64ccSRavi Bangoria reset_fds(fd1, nprocs); 559*c65c64ccSRavi Bangoria reset_fds(fd2, nprocs); 560*c65c64ccSRavi Bangoria enable_fds(fd1, nprocs); 561*c65c64ccSRavi Bangoria enable_fds(fd2, nprocs); 562*c65c64ccSRavi Bangoria multi_dawr_workload(); 563*c65c64ccSRavi Bangoria disable_fds(fd1, nprocs); 564*c65c64ccSRavi Bangoria disable_fds(fd2, nprocs); 565*c65c64ccSRavi Bangoria 566*c65c64ccSRavi Bangoria breaks1 = read_fds(fd1, nprocs); 567*c65c64ccSRavi Bangoria breaks2 = read_fds(fd2, nprocs); 568*c65c64ccSRavi Bangoria 569*c65c64ccSRavi Bangoria close_fds(fd1, nprocs); 570*c65c64ccSRavi Bangoria close_fds(fd2, nprocs); 571*c65c64ccSRavi Bangoria 572*c65c64ccSRavi Bangoria free(fd1); 573*c65c64ccSRavi Bangoria free(fd2); 574*c65c64ccSRavi Bangoria 575*c65c64ccSRavi Bangoria if (breaks1 != 2 || breaks2 != 2) { 576*c65c64ccSRavi Bangoria printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2); 577*c65c64ccSRavi Bangoria return 1; 578*c65c64ccSRavi Bangoria } 579*c65c64ccSRavi Bangoria 580*c65c64ccSRavi Bangoria printf("TESTED: %s\n", desc); 581*c65c64ccSRavi Bangoria return 0; 582*c65c64ccSRavi Bangoria } 583*c65c64ccSRavi Bangoria 584*c65c64ccSRavi Bangoria static int test_syswide_multi_same_addr(void) 585*c65c64ccSRavi Bangoria { 586*c65c64ccSRavi Bangoria unsigned long long breaks1 = 0, breaks2 = 0; 587*c65c64ccSRavi Bangoria int *fd1 = malloc(nprocs * sizeof(int)); 588*c65c64ccSRavi Bangoria int *fd2 = malloc(nprocs * sizeof(int)); 589*c65c64ccSRavi Bangoria char *desc = "Systemwide, Two events, same addr"; 590*c65c64ccSRavi Bangoria int ret; 591*c65c64ccSRavi Bangoria 592*c65c64ccSRavi Bangoria ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a)); 593*c65c64ccSRavi Bangoria if (ret) { 594*c65c64ccSRavi Bangoria perror("perf_systemwide_event_open"); 595*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 596*c65c64ccSRavi Bangoria } 597*c65c64ccSRavi Bangoria 598*c65c64ccSRavi Bangoria ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a)); 599*c65c64ccSRavi Bangoria if (ret) { 600*c65c64ccSRavi Bangoria close_fds(fd1, nprocs); 601*c65c64ccSRavi Bangoria perror("perf_systemwide_event_open"); 602*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 603*c65c64ccSRavi Bangoria } 604*c65c64ccSRavi Bangoria 605*c65c64ccSRavi Bangoria reset_fds(fd1, nprocs); 606*c65c64ccSRavi Bangoria reset_fds(fd2, nprocs); 607*c65c64ccSRavi Bangoria enable_fds(fd1, nprocs); 608*c65c64ccSRavi Bangoria enable_fds(fd2, nprocs); 609*c65c64ccSRavi Bangoria multi_dawr_workload(); 610*c65c64ccSRavi Bangoria disable_fds(fd1, nprocs); 611*c65c64ccSRavi Bangoria disable_fds(fd2, nprocs); 612*c65c64ccSRavi Bangoria 613*c65c64ccSRavi Bangoria breaks1 = read_fds(fd1, nprocs); 614*c65c64ccSRavi Bangoria breaks2 = read_fds(fd2, nprocs); 615*c65c64ccSRavi Bangoria 616*c65c64ccSRavi Bangoria close_fds(fd1, nprocs); 617*c65c64ccSRavi Bangoria close_fds(fd2, nprocs); 618*c65c64ccSRavi Bangoria 619*c65c64ccSRavi Bangoria free(fd1); 620*c65c64ccSRavi Bangoria free(fd2); 621*c65c64ccSRavi Bangoria 622*c65c64ccSRavi Bangoria if (breaks1 != 2 || breaks2 != 2) { 623*c65c64ccSRavi Bangoria printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2); 624*c65c64ccSRavi Bangoria return 1; 625*c65c64ccSRavi Bangoria } 626*c65c64ccSRavi Bangoria 627*c65c64ccSRavi Bangoria printf("TESTED: %s\n", desc); 628*c65c64ccSRavi Bangoria return 0; 629*c65c64ccSRavi Bangoria } 630*c65c64ccSRavi Bangoria 631*c65c64ccSRavi Bangoria static int test_syswide_multi_diff_addr_ro_wo(void) 632*c65c64ccSRavi Bangoria { 633*c65c64ccSRavi Bangoria unsigned long long breaks1 = 0, breaks2 = 0; 634*c65c64ccSRavi Bangoria int *fd1 = malloc(nprocs * sizeof(int)); 635*c65c64ccSRavi Bangoria int *fd2 = malloc(nprocs * sizeof(int)); 636*c65c64ccSRavi Bangoria char *desc = "Systemwide, Two events, diff addr, one is RO, other is WO"; 637*c65c64ccSRavi Bangoria int ret; 638*c65c64ccSRavi Bangoria 639*c65c64ccSRavi Bangoria ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a)); 640*c65c64ccSRavi Bangoria if (ret) { 641*c65c64ccSRavi Bangoria perror("perf_systemwide_event_open"); 642*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 643*c65c64ccSRavi Bangoria } 644*c65c64ccSRavi Bangoria 645*c65c64ccSRavi Bangoria ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_R, (__u64)&b, (__u64)sizeof(b)); 646*c65c64ccSRavi Bangoria if (ret) { 647*c65c64ccSRavi Bangoria close_fds(fd1, nprocs); 648*c65c64ccSRavi Bangoria perror("perf_systemwide_event_open"); 649*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 650*c65c64ccSRavi Bangoria } 651*c65c64ccSRavi Bangoria 652*c65c64ccSRavi Bangoria reset_fds(fd1, nprocs); 653*c65c64ccSRavi Bangoria reset_fds(fd2, nprocs); 654*c65c64ccSRavi Bangoria enable_fds(fd1, nprocs); 655*c65c64ccSRavi Bangoria enable_fds(fd2, nprocs); 656*c65c64ccSRavi Bangoria multi_dawr_workload(); 657*c65c64ccSRavi Bangoria disable_fds(fd1, nprocs); 658*c65c64ccSRavi Bangoria disable_fds(fd2, nprocs); 659*c65c64ccSRavi Bangoria 660*c65c64ccSRavi Bangoria breaks1 = read_fds(fd1, nprocs); 661*c65c64ccSRavi Bangoria breaks2 = read_fds(fd2, nprocs); 662*c65c64ccSRavi Bangoria 663*c65c64ccSRavi Bangoria close_fds(fd1, nprocs); 664*c65c64ccSRavi Bangoria close_fds(fd2, nprocs); 665*c65c64ccSRavi Bangoria 666*c65c64ccSRavi Bangoria free(fd1); 667*c65c64ccSRavi Bangoria free(fd2); 668*c65c64ccSRavi Bangoria 669*c65c64ccSRavi Bangoria if (breaks1 != 1 || breaks2 != 1) { 670*c65c64ccSRavi Bangoria printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2); 671*c65c64ccSRavi Bangoria return 1; 672*c65c64ccSRavi Bangoria } 673*c65c64ccSRavi Bangoria 674*c65c64ccSRavi Bangoria printf("TESTED: %s\n", desc); 675*c65c64ccSRavi Bangoria return 0; 676*c65c64ccSRavi Bangoria } 677*c65c64ccSRavi Bangoria 678*c65c64ccSRavi Bangoria static int test_syswide_multi_same_addr_ro_wo(void) 679*c65c64ccSRavi Bangoria { 680*c65c64ccSRavi Bangoria unsigned long long breaks1 = 0, breaks2 = 0; 681*c65c64ccSRavi Bangoria int *fd1 = malloc(nprocs * sizeof(int)); 682*c65c64ccSRavi Bangoria int *fd2 = malloc(nprocs * sizeof(int)); 683*c65c64ccSRavi Bangoria char *desc = "Systemwide, Two events, same addr, one is RO, other is WO"; 684*c65c64ccSRavi Bangoria int ret; 685*c65c64ccSRavi Bangoria 686*c65c64ccSRavi Bangoria ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a)); 687*c65c64ccSRavi Bangoria if (ret) { 688*c65c64ccSRavi Bangoria perror("perf_systemwide_event_open"); 689*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 690*c65c64ccSRavi Bangoria } 691*c65c64ccSRavi Bangoria 692*c65c64ccSRavi Bangoria ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_R, (__u64)&a, (__u64)sizeof(a)); 693*c65c64ccSRavi Bangoria if (ret) { 694*c65c64ccSRavi Bangoria close_fds(fd1, nprocs); 695*c65c64ccSRavi Bangoria perror("perf_systemwide_event_open"); 696*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 697*c65c64ccSRavi Bangoria } 698*c65c64ccSRavi Bangoria 699*c65c64ccSRavi Bangoria reset_fds(fd1, nprocs); 700*c65c64ccSRavi Bangoria reset_fds(fd2, nprocs); 701*c65c64ccSRavi Bangoria enable_fds(fd1, nprocs); 702*c65c64ccSRavi Bangoria enable_fds(fd2, nprocs); 703*c65c64ccSRavi Bangoria multi_dawr_workload(); 704*c65c64ccSRavi Bangoria disable_fds(fd1, nprocs); 705*c65c64ccSRavi Bangoria disable_fds(fd2, nprocs); 706*c65c64ccSRavi Bangoria 707*c65c64ccSRavi Bangoria breaks1 = read_fds(fd1, nprocs); 708*c65c64ccSRavi Bangoria breaks2 = read_fds(fd2, nprocs); 709*c65c64ccSRavi Bangoria 710*c65c64ccSRavi Bangoria close_fds(fd1, nprocs); 711*c65c64ccSRavi Bangoria close_fds(fd2, nprocs); 712*c65c64ccSRavi Bangoria 713*c65c64ccSRavi Bangoria free(fd1); 714*c65c64ccSRavi Bangoria free(fd2); 715*c65c64ccSRavi Bangoria 716*c65c64ccSRavi Bangoria if (breaks1 != 1 || breaks2 != 1) { 717*c65c64ccSRavi Bangoria printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2); 718*c65c64ccSRavi Bangoria return 1; 719*c65c64ccSRavi Bangoria } 720*c65c64ccSRavi Bangoria 721*c65c64ccSRavi Bangoria printf("TESTED: %s\n", desc); 722*c65c64ccSRavi Bangoria return 0; 723*c65c64ccSRavi Bangoria } 724*c65c64ccSRavi Bangoria 725*c65c64ccSRavi Bangoria static int runtest_multi_dawr(void) 726*c65c64ccSRavi Bangoria { 727*c65c64ccSRavi Bangoria int ret = 0; 728*c65c64ccSRavi Bangoria 729*c65c64ccSRavi Bangoria ret |= test_process_multi_diff_addr(); 730*c65c64ccSRavi Bangoria ret |= test_process_multi_same_addr(); 731*c65c64ccSRavi Bangoria ret |= test_process_multi_diff_addr_ro_wo(); 732*c65c64ccSRavi Bangoria ret |= test_process_multi_same_addr_ro_wo(); 733*c65c64ccSRavi Bangoria ret |= test_syswide_multi_diff_addr(); 734*c65c64ccSRavi Bangoria ret |= test_syswide_multi_same_addr(); 735*c65c64ccSRavi Bangoria ret |= test_syswide_multi_diff_addr_ro_wo(); 736*c65c64ccSRavi Bangoria ret |= test_syswide_multi_same_addr_ro_wo(); 737*c65c64ccSRavi Bangoria 738*c65c64ccSRavi Bangoria return ret; 739*c65c64ccSRavi Bangoria } 740*c65c64ccSRavi Bangoria 741*c65c64ccSRavi Bangoria static int runtest_unaligned_512bytes(void) 742*c65c64ccSRavi Bangoria { 743*c65c64ccSRavi Bangoria unsigned long long breaks = 0; 744*c65c64ccSRavi Bangoria int fd; 745*c65c64ccSRavi Bangoria char *desc = "Process specific, 512 bytes, unaligned"; 746*c65c64ccSRavi Bangoria __u64 addr = (__u64)&c + 8; 747*c65c64ccSRavi Bangoria size_t res; 748*c65c64ccSRavi Bangoria 749*c65c64ccSRavi Bangoria fd = perf_process_event_open(HW_BREAKPOINT_RW, addr, 512); 750*c65c64ccSRavi Bangoria if (fd < 0) { 751*c65c64ccSRavi Bangoria perror("perf_process_event_open"); 752*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 753*c65c64ccSRavi Bangoria } 754*c65c64ccSRavi Bangoria 755*c65c64ccSRavi Bangoria ioctl(fd, PERF_EVENT_IOC_RESET); 756*c65c64ccSRavi Bangoria ioctl(fd, PERF_EVENT_IOC_ENABLE); 757*c65c64ccSRavi Bangoria multi_dawr_workload(); 758*c65c64ccSRavi Bangoria ioctl(fd, PERF_EVENT_IOC_DISABLE); 759*c65c64ccSRavi Bangoria 760*c65c64ccSRavi Bangoria res = read(fd, &breaks, sizeof(breaks)); 761*c65c64ccSRavi Bangoria assert(res == sizeof(unsigned long long)); 762*c65c64ccSRavi Bangoria 763*c65c64ccSRavi Bangoria close(fd); 764*c65c64ccSRavi Bangoria 765*c65c64ccSRavi Bangoria if (breaks != 2) { 766*c65c64ccSRavi Bangoria printf("FAILED: %s: %lld != 2\n", desc, breaks); 767*c65c64ccSRavi Bangoria return 1; 768*c65c64ccSRavi Bangoria } 769*c65c64ccSRavi Bangoria 770*c65c64ccSRavi Bangoria printf("TESTED: %s\n", desc); 771*c65c64ccSRavi Bangoria return 0; 772*c65c64ccSRavi Bangoria } 773*c65c64ccSRavi Bangoria 774*c65c64ccSRavi Bangoria /* There is no perf api to find number of available watchpoints. Use ptrace. */ 775*c65c64ccSRavi Bangoria static int get_nr_wps(bool *arch_31) 776*c65c64ccSRavi Bangoria { 777*c65c64ccSRavi Bangoria struct ppc_debug_info dbginfo; 778*c65c64ccSRavi Bangoria int child_pid; 779*c65c64ccSRavi Bangoria 780*c65c64ccSRavi Bangoria child_pid = fork(); 781*c65c64ccSRavi Bangoria if (!child_pid) { 782*c65c64ccSRavi Bangoria int ret = ptrace(PTRACE_TRACEME, 0, NULL, 0); 783*c65c64ccSRavi Bangoria if (ret) { 784*c65c64ccSRavi Bangoria perror("PTRACE_TRACEME failed\n"); 785*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 786*c65c64ccSRavi Bangoria } 787*c65c64ccSRavi Bangoria kill(getpid(), SIGUSR1); 788*c65c64ccSRavi Bangoria 789*c65c64ccSRavi Bangoria sleep(1); 790*c65c64ccSRavi Bangoria exit(EXIT_SUCCESS); 791*c65c64ccSRavi Bangoria } 792*c65c64ccSRavi Bangoria 793*c65c64ccSRavi Bangoria wait(NULL); 794*c65c64ccSRavi Bangoria if (ptrace(PPC_PTRACE_GETHWDBGINFO, child_pid, NULL, &dbginfo)) { 795*c65c64ccSRavi Bangoria perror("Can't get breakpoint info"); 796*c65c64ccSRavi Bangoria exit(EXIT_FAILURE); 797*c65c64ccSRavi Bangoria } 798*c65c64ccSRavi Bangoria 799*c65c64ccSRavi Bangoria *arch_31 = !!(dbginfo.features & PPC_DEBUG_FEATURE_DATA_BP_ARCH_31); 800*c65c64ccSRavi Bangoria return dbginfo.num_data_bps; 801*c65c64ccSRavi Bangoria } 802*c65c64ccSRavi Bangoria 8039c2d72d4SMichael Neuling static int runtest(void) 8049c2d72d4SMichael Neuling { 8059c2d72d4SMichael Neuling int rwflag; 8069c2d72d4SMichael Neuling int exclude_user; 8079c2d72d4SMichael Neuling int ret; 808*c65c64ccSRavi Bangoria bool dawr = dawr_supported(); 809*c65c64ccSRavi Bangoria bool arch_31 = false; 810*c65c64ccSRavi Bangoria int nr_wps = get_nr_wps(&arch_31); 8119c2d72d4SMichael Neuling 8129c2d72d4SMichael Neuling /* 8139c2d72d4SMichael Neuling * perf defines rwflag as two bits read and write and at least 8149c2d72d4SMichael Neuling * one must be set. So range 1-3. 8159c2d72d4SMichael Neuling */ 8169c2d72d4SMichael Neuling for (rwflag = 1 ; rwflag < 4; rwflag++) { 8179c2d72d4SMichael Neuling for (exclude_user = 0 ; exclude_user < 2; exclude_user++) { 8189c2d72d4SMichael Neuling ret = runtestsingle(rwflag, exclude_user, 0); 8199c2d72d4SMichael Neuling if (ret) 8209c2d72d4SMichael Neuling return ret; 8219c2d72d4SMichael Neuling 8229c2d72d4SMichael Neuling /* if we have the dawr, we can do an array test */ 823*c65c64ccSRavi Bangoria if (!dawr) 8249c2d72d4SMichael Neuling continue; 8259c2d72d4SMichael Neuling ret = runtestsingle(rwflag, exclude_user, 1); 8269c2d72d4SMichael Neuling if (ret) 8279c2d72d4SMichael Neuling return ret; 8289c2d72d4SMichael Neuling } 8299c2d72d4SMichael Neuling } 830949758a2SRavi Bangoria 831949758a2SRavi Bangoria ret = runtest_dar_outside(); 832*c65c64ccSRavi Bangoria if (ret) 833*c65c64ccSRavi Bangoria return ret; 834*c65c64ccSRavi Bangoria 835*c65c64ccSRavi Bangoria if (dawr && nr_wps > 1) { 836*c65c64ccSRavi Bangoria nprocs = get_nprocs(); 837*c65c64ccSRavi Bangoria ret = runtest_multi_dawr(); 838*c65c64ccSRavi Bangoria if (ret) 839*c65c64ccSRavi Bangoria return ret; 840*c65c64ccSRavi Bangoria } 841*c65c64ccSRavi Bangoria 842*c65c64ccSRavi Bangoria if (dawr && arch_31) 843*c65c64ccSRavi Bangoria ret = runtest_unaligned_512bytes(); 844*c65c64ccSRavi Bangoria 845949758a2SRavi Bangoria return ret; 8469c2d72d4SMichael Neuling } 8479c2d72d4SMichael Neuling 8489c2d72d4SMichael Neuling 8499c2d72d4SMichael Neuling static int perf_hwbreak(void) 8509c2d72d4SMichael Neuling { 8519c2d72d4SMichael Neuling srand ( time(NULL) ); 8529c2d72d4SMichael Neuling 8539c2d72d4SMichael Neuling SKIP_IF(!perf_breakpoint_supported()); 8549c2d72d4SMichael Neuling 8559c2d72d4SMichael Neuling return runtest(); 8569c2d72d4SMichael Neuling } 8579c2d72d4SMichael Neuling 8589c2d72d4SMichael Neuling int main(int argc, char *argv[], char **envp) 8599c2d72d4SMichael Neuling { 8609c2d72d4SMichael Neuling return test_harness(perf_hwbreak, "perf_hwbreak"); 8619c2d72d4SMichael Neuling } 862