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