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 
2026009592SNaveen N. Rao #define _GNU_SOURCE
2126009592SNaveen N. Rao 
229c2d72d4SMichael Neuling #include <unistd.h>
239c2d72d4SMichael Neuling #include <assert.h>
2426009592SNaveen N. Rao #include <sched.h>
259c2d72d4SMichael Neuling #include <stdio.h>
269c2d72d4SMichael Neuling #include <stdlib.h>
27c65c64ccSRavi Bangoria #include <signal.h>
289c2d72d4SMichael Neuling #include <string.h>
299c2d72d4SMichael Neuling #include <sys/ioctl.h>
30c65c64ccSRavi Bangoria #include <sys/wait.h>
31c65c64ccSRavi Bangoria #include <sys/ptrace.h>
32616ad3f4SNaveen N. Rao #include <sys/resource.h>
33c65c64ccSRavi Bangoria #include <sys/sysinfo.h>
34c65c64ccSRavi Bangoria #include <asm/ptrace.h>
359c2d72d4SMichael Neuling #include <elf.h>
369c2d72d4SMichael Neuling #include <pthread.h>
379c2d72d4SMichael Neuling #include <sys/syscall.h>
389c2d72d4SMichael Neuling #include <linux/perf_event.h>
399c2d72d4SMichael Neuling #include <linux/hw_breakpoint.h>
409c2d72d4SMichael Neuling #include "utils.h"
419c2d72d4SMichael Neuling 
42dae4ff80SRavi Bangoria #ifndef PPC_DEBUG_FEATURE_DATA_BP_ARCH_31
43dae4ff80SRavi Bangoria #define PPC_DEBUG_FEATURE_DATA_BP_ARCH_31	0x20
44dae4ff80SRavi Bangoria #endif
45dae4ff80SRavi Bangoria 
469c2d72d4SMichael Neuling #define MAX_LOOPS 10000
479c2d72d4SMichael Neuling 
489c2d72d4SMichael Neuling #define DAWR_LENGTH_MAX ((0x3f + 1) * 8)
499c2d72d4SMichael Neuling 
50c65c64ccSRavi Bangoria int nprocs;
51c65c64ccSRavi Bangoria 
52c65c64ccSRavi Bangoria static volatile int a = 10;
53c65c64ccSRavi Bangoria static volatile int b = 10;
54c65c64ccSRavi Bangoria static volatile char c[512 + 8] __attribute__((aligned(512)));
55c65c64ccSRavi Bangoria 
perf_event_attr_set(struct perf_event_attr * attr,__u32 type,__u64 addr,__u64 len,bool exclude_user)56c9cb0afbSRavi Bangoria static void perf_event_attr_set(struct perf_event_attr *attr,
57c9cb0afbSRavi Bangoria 				__u32 type, __u64 addr, __u64 len,
58c9cb0afbSRavi Bangoria 				bool exclude_user)
599c2d72d4SMichael Neuling {
60c9cb0afbSRavi Bangoria 	memset(attr, 0, sizeof(struct perf_event_attr));
61c9cb0afbSRavi Bangoria 	attr->type           = PERF_TYPE_BREAKPOINT;
62c9cb0afbSRavi Bangoria 	attr->size           = sizeof(struct perf_event_attr);
63c9cb0afbSRavi Bangoria 	attr->bp_type        = type;
64c9cb0afbSRavi Bangoria 	attr->bp_addr        = addr;
65c9cb0afbSRavi Bangoria 	attr->bp_len         = len;
66c9cb0afbSRavi Bangoria 	attr->exclude_kernel = 1;
67c9cb0afbSRavi Bangoria 	attr->exclude_hv     = 1;
68c9cb0afbSRavi Bangoria 	attr->exclude_guest  = 1;
69c9cb0afbSRavi Bangoria 	attr->exclude_user   = exclude_user;
70c9cb0afbSRavi Bangoria 	attr->disabled       = 1;
71c9cb0afbSRavi Bangoria }
72c9cb0afbSRavi Bangoria 
73c9cb0afbSRavi Bangoria static int
perf_process_event_open_exclude_user(__u32 type,__u64 addr,__u64 len,bool exclude_user)74c9cb0afbSRavi Bangoria perf_process_event_open_exclude_user(__u32 type, __u64 addr, __u64 len, bool exclude_user)
75c9cb0afbSRavi Bangoria {
76c9cb0afbSRavi Bangoria 	struct perf_event_attr attr;
77c9cb0afbSRavi Bangoria 
78c9cb0afbSRavi Bangoria 	perf_event_attr_set(&attr, type, addr, len, exclude_user);
79c9cb0afbSRavi Bangoria 	return syscall(__NR_perf_event_open, &attr, getpid(), -1, -1, 0);
80c9cb0afbSRavi Bangoria }
81c9cb0afbSRavi Bangoria 
perf_process_event_open(__u32 type,__u64 addr,__u64 len)82c9cb0afbSRavi Bangoria static int perf_process_event_open(__u32 type, __u64 addr, __u64 len)
83c9cb0afbSRavi Bangoria {
84c9cb0afbSRavi Bangoria 	struct perf_event_attr attr;
85c9cb0afbSRavi Bangoria 
86c9cb0afbSRavi Bangoria 	perf_event_attr_set(&attr, type, addr, len, 0);
87c9cb0afbSRavi Bangoria 	return syscall(__NR_perf_event_open, &attr, getpid(), -1, -1, 0);
889c2d72d4SMichael Neuling }
899c2d72d4SMichael Neuling 
perf_cpu_event_open(long cpu,__u32 type,__u64 addr,__u64 len)90c65c64ccSRavi Bangoria static int perf_cpu_event_open(long cpu, __u32 type, __u64 addr, __u64 len)
91c65c64ccSRavi Bangoria {
92c65c64ccSRavi Bangoria 	struct perf_event_attr attr;
93c65c64ccSRavi Bangoria 
94c65c64ccSRavi Bangoria 	perf_event_attr_set(&attr, type, addr, len, 0);
95c65c64ccSRavi Bangoria 	return syscall(__NR_perf_event_open, &attr, -1, cpu, -1, 0);
96c65c64ccSRavi Bangoria }
97c65c64ccSRavi Bangoria 
close_fds(int * fd,int n)98c65c64ccSRavi Bangoria static void close_fds(int *fd, int n)
99c65c64ccSRavi Bangoria {
100c65c64ccSRavi Bangoria 	int i;
101c65c64ccSRavi Bangoria 
102c65c64ccSRavi Bangoria 	for (i = 0; i < n; i++)
103c65c64ccSRavi Bangoria 		close(fd[i]);
104c65c64ccSRavi Bangoria }
105c65c64ccSRavi Bangoria 
read_fds(int * fd,int n)106c65c64ccSRavi Bangoria static unsigned long read_fds(int *fd, int n)
107c65c64ccSRavi Bangoria {
108c65c64ccSRavi Bangoria 	int i;
109c65c64ccSRavi Bangoria 	unsigned long c = 0;
110c65c64ccSRavi Bangoria 	unsigned long count = 0;
111c65c64ccSRavi Bangoria 	size_t res;
112c65c64ccSRavi Bangoria 
113c65c64ccSRavi Bangoria 	for (i = 0; i < n; i++) {
114c65c64ccSRavi Bangoria 		res = read(fd[i], &c, sizeof(c));
115c65c64ccSRavi Bangoria 		assert(res == sizeof(unsigned long long));
116c65c64ccSRavi Bangoria 		count += c;
117c65c64ccSRavi Bangoria 	}
118c65c64ccSRavi Bangoria 	return count;
119c65c64ccSRavi Bangoria }
120c65c64ccSRavi Bangoria 
reset_fds(int * fd,int n)121c65c64ccSRavi Bangoria static void reset_fds(int *fd, int n)
122c65c64ccSRavi Bangoria {
123c65c64ccSRavi Bangoria 	int i;
124c65c64ccSRavi Bangoria 
125c65c64ccSRavi Bangoria 	for (i = 0; i < n; i++)
126c65c64ccSRavi Bangoria 		ioctl(fd[i], PERF_EVENT_IOC_RESET);
127c65c64ccSRavi Bangoria }
128c65c64ccSRavi Bangoria 
enable_fds(int * fd,int n)129c65c64ccSRavi Bangoria static void enable_fds(int *fd, int n)
130c65c64ccSRavi Bangoria {
131c65c64ccSRavi Bangoria 	int i;
132c65c64ccSRavi Bangoria 
133c65c64ccSRavi Bangoria 	for (i = 0; i < n; i++)
134c65c64ccSRavi Bangoria 		ioctl(fd[i], PERF_EVENT_IOC_ENABLE);
135c65c64ccSRavi Bangoria }
136c65c64ccSRavi Bangoria 
disable_fds(int * fd,int n)137c65c64ccSRavi Bangoria static void disable_fds(int *fd, int n)
138c65c64ccSRavi Bangoria {
139c65c64ccSRavi Bangoria 	int i;
140c65c64ccSRavi Bangoria 
141c65c64ccSRavi Bangoria 	for (i = 0; i < n; i++)
142c65c64ccSRavi Bangoria 		ioctl(fd[i], PERF_EVENT_IOC_DISABLE);
143c65c64ccSRavi Bangoria }
144c65c64ccSRavi Bangoria 
perf_systemwide_event_open(int * fd,__u32 type,__u64 addr,__u64 len)145c65c64ccSRavi Bangoria static int perf_systemwide_event_open(int *fd, __u32 type, __u64 addr, __u64 len)
146c65c64ccSRavi Bangoria {
14726009592SNaveen N. Rao 	int i, ncpus, cpu, ret = 0;
148616ad3f4SNaveen N. Rao 	struct rlimit rlim;
14926009592SNaveen N. Rao 	cpu_set_t *mask;
15026009592SNaveen N. Rao 	size_t size;
151c65c64ccSRavi Bangoria 
152616ad3f4SNaveen N. Rao 	if (getrlimit(RLIMIT_NOFILE, &rlim)) {
153616ad3f4SNaveen N. Rao 		perror("getrlimit");
154616ad3f4SNaveen N. Rao 		return -1;
155616ad3f4SNaveen N. Rao 	}
156616ad3f4SNaveen N. Rao 	rlim.rlim_cur = 65536;
157616ad3f4SNaveen N. Rao 	if (setrlimit(RLIMIT_NOFILE, &rlim)) {
158616ad3f4SNaveen N. Rao 		perror("setrlimit");
159616ad3f4SNaveen N. Rao 		return -1;
160616ad3f4SNaveen N. Rao 	}
161616ad3f4SNaveen N. Rao 
16226009592SNaveen N. Rao 	ncpus = get_nprocs_conf();
16326009592SNaveen N. Rao 	size = CPU_ALLOC_SIZE(ncpus);
16426009592SNaveen N. Rao 	mask = CPU_ALLOC(ncpus);
16526009592SNaveen N. Rao 	if (!mask) {
16626009592SNaveen N. Rao 		perror("malloc");
16726009592SNaveen N. Rao 		return -1;
16826009592SNaveen N. Rao 	}
16926009592SNaveen N. Rao 
17026009592SNaveen N. Rao 	CPU_ZERO_S(size, mask);
17126009592SNaveen N. Rao 
17226009592SNaveen N. Rao 	if (sched_getaffinity(0, size, mask)) {
17326009592SNaveen N. Rao 		perror("sched_getaffinity");
17426009592SNaveen N. Rao 		ret = -1;
17526009592SNaveen N. Rao 		goto done;
17626009592SNaveen N. Rao 	}
17726009592SNaveen N. Rao 
17826009592SNaveen N. Rao 	for (i = 0, cpu = 0; i < nprocs && cpu < ncpus; cpu++) {
17926009592SNaveen N. Rao 		if (!CPU_ISSET_S(cpu, size, mask))
18026009592SNaveen N. Rao 			continue;
18126009592SNaveen N. Rao 		fd[i] = perf_cpu_event_open(cpu, type, addr, len);
182c65c64ccSRavi Bangoria 		if (fd[i] < 0) {
18371ae6305SNaveen N. Rao 			perror("perf_systemwide_event_open");
184c65c64ccSRavi Bangoria 			close_fds(fd, i);
18526009592SNaveen N. Rao 			ret = fd[i];
18626009592SNaveen N. Rao 			goto done;
187c65c64ccSRavi Bangoria 		}
18826009592SNaveen N. Rao 		i++;
189c65c64ccSRavi Bangoria 	}
19026009592SNaveen N. Rao 
19126009592SNaveen N. Rao 	if (i < nprocs) {
19226009592SNaveen N. Rao 		printf("Error: Number of online cpus reduced since start of test: %d < %d\n", i, nprocs);
19326009592SNaveen N. Rao 		close_fds(fd, i);
19426009592SNaveen N. Rao 		ret = -1;
19526009592SNaveen N. Rao 	}
19626009592SNaveen N. Rao 
19726009592SNaveen N. Rao done:
19826009592SNaveen N. Rao 	CPU_FREE(mask);
19926009592SNaveen N. Rao 	return ret;
200c65c64ccSRavi Bangoria }
201c65c64ccSRavi Bangoria 
breakpoint_test(int len)2029c2d72d4SMichael Neuling static inline bool breakpoint_test(int len)
2039c2d72d4SMichael Neuling {
2049c2d72d4SMichael Neuling 	int fd;
2059c2d72d4SMichael Neuling 
2069c2d72d4SMichael Neuling 	/* bp_addr can point anywhere but needs to be aligned */
207c9cb0afbSRavi Bangoria 	fd = perf_process_event_open(HW_BREAKPOINT_R, (__u64)(&fd) & 0xfffffffffffff800, len);
2089c2d72d4SMichael Neuling 	if (fd < 0)
2099c2d72d4SMichael Neuling 		return false;
2109c2d72d4SMichael Neuling 	close(fd);
2119c2d72d4SMichael Neuling 	return true;
2129c2d72d4SMichael Neuling }
2139c2d72d4SMichael Neuling 
perf_breakpoint_supported(void)2149c2d72d4SMichael Neuling static inline bool perf_breakpoint_supported(void)
2159c2d72d4SMichael Neuling {
2169c2d72d4SMichael Neuling 	return breakpoint_test(4);
2179c2d72d4SMichael Neuling }
2189c2d72d4SMichael Neuling 
dawr_supported(void)2199c2d72d4SMichael Neuling static inline bool dawr_supported(void)
2209c2d72d4SMichael Neuling {
2219c2d72d4SMichael Neuling 	return breakpoint_test(DAWR_LENGTH_MAX);
2229c2d72d4SMichael Neuling }
2239c2d72d4SMichael Neuling 
runtestsingle(int readwriteflag,int exclude_user,int arraytest)2249c2d72d4SMichael Neuling static int runtestsingle(int readwriteflag, int exclude_user, int arraytest)
2259c2d72d4SMichael Neuling {
2269c2d72d4SMichael Neuling 	int i,j;
2279c2d72d4SMichael Neuling 	size_t res;
2289c2d72d4SMichael Neuling 	unsigned long long breaks, needed;
2299c2d72d4SMichael Neuling 	int readint;
2309c2d72d4SMichael Neuling 	int readintarraybig[2*DAWR_LENGTH_MAX/sizeof(int)];
2319c2d72d4SMichael Neuling 	int *readintalign;
2329c2d72d4SMichael Neuling 	volatile int *ptr;
2339c2d72d4SMichael Neuling 	int break_fd;
2349c2d72d4SMichael Neuling 	int loop_num = MAX_LOOPS - (rand() % 100); /* provide some variability */
2359c2d72d4SMichael Neuling 	volatile int *k;
236c9cb0afbSRavi Bangoria 	__u64 len;
2379c2d72d4SMichael Neuling 
2389c2d72d4SMichael Neuling 	/* align to 0x400 boundary as required by DAWR */
2399c2d72d4SMichael Neuling 	readintalign = (int *)(((unsigned long)readintarraybig + 0x7ff) &
2409c2d72d4SMichael Neuling 			       0xfffffffffffff800);
2419c2d72d4SMichael Neuling 
2429c2d72d4SMichael Neuling 	ptr = &readint;
2439c2d72d4SMichael Neuling 	if (arraytest)
2449c2d72d4SMichael Neuling 		ptr = &readintalign[0];
2459c2d72d4SMichael Neuling 
246c9cb0afbSRavi Bangoria 	len = arraytest ? DAWR_LENGTH_MAX : sizeof(int);
247c9cb0afbSRavi Bangoria 	break_fd = perf_process_event_open_exclude_user(readwriteflag, (__u64)ptr,
248c9cb0afbSRavi Bangoria 							len, exclude_user);
2499c2d72d4SMichael Neuling 	if (break_fd < 0) {
250c9cb0afbSRavi Bangoria 		perror("perf_process_event_open_exclude_user");
2519c2d72d4SMichael Neuling 		exit(1);
2529c2d72d4SMichael Neuling 	}
2539c2d72d4SMichael Neuling 
2549c2d72d4SMichael Neuling 	/* start counters */
2559c2d72d4SMichael Neuling 	ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
2569c2d72d4SMichael Neuling 
2579c2d72d4SMichael Neuling 	/* Test a bunch of reads and writes */
2589c2d72d4SMichael Neuling 	k = &readint;
2599c2d72d4SMichael Neuling 	for (i = 0; i < loop_num; i++) {
2609c2d72d4SMichael Neuling 		if (arraytest)
2619c2d72d4SMichael Neuling 			k = &(readintalign[i % (DAWR_LENGTH_MAX/sizeof(int))]);
2629c2d72d4SMichael Neuling 
2639c2d72d4SMichael Neuling 		j = *k;
2649c2d72d4SMichael Neuling 		*k = j;
2659c2d72d4SMichael Neuling 	}
2669c2d72d4SMichael Neuling 
2679c2d72d4SMichael Neuling 	/* stop counters */
2689c2d72d4SMichael Neuling 	ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
2699c2d72d4SMichael Neuling 
2709c2d72d4SMichael Neuling 	/* read and check counters */
2719c2d72d4SMichael Neuling 	res = read(break_fd, &breaks, sizeof(unsigned long long));
2729c2d72d4SMichael Neuling 	assert(res == sizeof(unsigned long long));
2739c2d72d4SMichael Neuling 	/* we read and write each loop, so subtract the ones we are counting */
2749c2d72d4SMichael Neuling 	needed = 0;
2759c2d72d4SMichael Neuling 	if (readwriteflag & HW_BREAKPOINT_R)
2769c2d72d4SMichael Neuling 		needed += loop_num;
2779c2d72d4SMichael Neuling 	if (readwriteflag & HW_BREAKPOINT_W)
2789c2d72d4SMichael Neuling 		needed += loop_num;
2799c2d72d4SMichael Neuling 	needed = needed * (1 - exclude_user);
2809c2d72d4SMichael Neuling 	printf("TESTED: addr:0x%lx brks:% 8lld loops:% 8i rw:%i !user:%i array:%i\n",
2819c2d72d4SMichael Neuling 	       (unsigned long int)ptr, breaks, loop_num, readwriteflag, exclude_user, arraytest);
2829c2d72d4SMichael Neuling 	if (breaks != needed) {
2839c2d72d4SMichael Neuling 		printf("FAILED: 0x%lx brks:%lld needed:%lli %i %i %i\n\n",
2849c2d72d4SMichael Neuling 		       (unsigned long int)ptr, breaks, needed, loop_num, readwriteflag, exclude_user);
2859c2d72d4SMichael Neuling 		return 1;
2869c2d72d4SMichael Neuling 	}
2879c2d72d4SMichael Neuling 	close(break_fd);
2889c2d72d4SMichael Neuling 
2899c2d72d4SMichael Neuling 	return 0;
2909c2d72d4SMichael Neuling }
2919c2d72d4SMichael Neuling 
runtest_dar_outside(void)292949758a2SRavi Bangoria static int runtest_dar_outside(void)
293949758a2SRavi Bangoria {
294949758a2SRavi Bangoria 	void *target;
295949758a2SRavi Bangoria 	volatile __u16 temp16;
296949758a2SRavi Bangoria 	volatile __u64 temp64;
297949758a2SRavi Bangoria 	int break_fd;
298949758a2SRavi Bangoria 	unsigned long long breaks;
299949758a2SRavi Bangoria 	int fail = 0;
300949758a2SRavi Bangoria 	size_t res;
301949758a2SRavi Bangoria 
302949758a2SRavi Bangoria 	target = malloc(8);
303949758a2SRavi Bangoria 	if (!target) {
304949758a2SRavi Bangoria 		perror("malloc failed");
305949758a2SRavi Bangoria 		exit(EXIT_FAILURE);
306949758a2SRavi Bangoria 	}
307949758a2SRavi Bangoria 
308949758a2SRavi Bangoria 	/* watch middle half of target array */
309c9cb0afbSRavi Bangoria 	break_fd = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)(target + 2), 4);
310949758a2SRavi Bangoria 	if (break_fd < 0) {
311949758a2SRavi Bangoria 		free(target);
312c9cb0afbSRavi Bangoria 		perror("perf_process_event_open");
313949758a2SRavi Bangoria 		exit(EXIT_FAILURE);
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);
320949758a2SRavi Bangoria 	*((__u16 *)target) = 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 	temp16 = *((__u16 *)(target + 1));
335949758a2SRavi Bangoria 	*((__u16 *)(target + 1)) = temp16;
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: Partial overlap\n");
341949758a2SRavi Bangoria 	} else {
342949758a2SRavi Bangoria 		printf("FAILED: Partial overlap: %lld != 2\n", breaks);
343949758a2SRavi Bangoria 		fail = 1;
344949758a2SRavi Bangoria 	}
345949758a2SRavi Bangoria 
346949758a2SRavi Bangoria 	/* Hit */
347949758a2SRavi Bangoria 	ioctl(break_fd, PERF_EVENT_IOC_RESET);
348949758a2SRavi Bangoria 	ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
349949758a2SRavi Bangoria 	temp16 = *((__u16 *)(target + 5));
350949758a2SRavi Bangoria 	*((__u16 *)(target + 5)) = temp16;
351949758a2SRavi Bangoria 	ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
352949758a2SRavi Bangoria 	res = read(break_fd, &breaks, sizeof(unsigned long long));
353949758a2SRavi Bangoria 	assert(res == sizeof(unsigned long long));
354949758a2SRavi Bangoria 	if (breaks == 2) {
355949758a2SRavi Bangoria 		printf("TESTED: Partial overlap\n");
356949758a2SRavi Bangoria 	} else {
357949758a2SRavi Bangoria 		printf("FAILED: Partial overlap: %lld != 2\n", breaks);
358949758a2SRavi Bangoria 		fail = 1;
359949758a2SRavi Bangoria 	}
360949758a2SRavi Bangoria 
361949758a2SRavi Bangoria 	/* Shouldn't Hit */
362949758a2SRavi Bangoria 	ioctl(break_fd, PERF_EVENT_IOC_RESET);
363949758a2SRavi Bangoria 	ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
364949758a2SRavi Bangoria 	temp16 = *((__u16 *)(target + 6));
365949758a2SRavi Bangoria 	*((__u16 *)(target + 6)) = temp16;
366949758a2SRavi Bangoria 	ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
367949758a2SRavi Bangoria 	res = read(break_fd, &breaks, sizeof(unsigned long long));
368949758a2SRavi Bangoria 	assert(res == sizeof(unsigned long long));
369949758a2SRavi Bangoria 	if (breaks == 0) {
370949758a2SRavi Bangoria 		printf("TESTED: No overlap\n");
371949758a2SRavi Bangoria 	} else {
372949758a2SRavi Bangoria 		printf("FAILED: No overlap: %lld != 0\n", breaks);
373949758a2SRavi Bangoria 		fail = 1;
374949758a2SRavi Bangoria 	}
375949758a2SRavi Bangoria 
376949758a2SRavi Bangoria 	/* Hit */
377949758a2SRavi Bangoria 	ioctl(break_fd, PERF_EVENT_IOC_RESET);
378949758a2SRavi Bangoria 	ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
379949758a2SRavi Bangoria 	temp64 = *((__u64 *)target);
380949758a2SRavi Bangoria 	*((__u64 *)target) = temp64;
381949758a2SRavi Bangoria 	ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
382949758a2SRavi Bangoria 	res = read(break_fd, &breaks, sizeof(unsigned long long));
383949758a2SRavi Bangoria 	assert(res == sizeof(unsigned long long));
384949758a2SRavi Bangoria 	if (breaks == 2) {
385949758a2SRavi Bangoria 		printf("TESTED: Full overlap\n");
386949758a2SRavi Bangoria 	} else {
387949758a2SRavi Bangoria 		printf("FAILED: Full overlap: %lld != 2\n", breaks);
388949758a2SRavi Bangoria 		fail = 1;
389949758a2SRavi Bangoria 	}
390949758a2SRavi Bangoria 
391949758a2SRavi Bangoria 	free(target);
392949758a2SRavi Bangoria 	close(break_fd);
393949758a2SRavi Bangoria 	return fail;
394949758a2SRavi Bangoria }
395949758a2SRavi Bangoria 
multi_dawr_workload(void)396c65c64ccSRavi Bangoria static void multi_dawr_workload(void)
397c65c64ccSRavi Bangoria {
398c65c64ccSRavi Bangoria 	a += 10;
399c65c64ccSRavi Bangoria 	b += 10;
400c65c64ccSRavi Bangoria 	c[512 + 1] += 'a';
401c65c64ccSRavi Bangoria }
402c65c64ccSRavi Bangoria 
test_process_multi_diff_addr(void)403c65c64ccSRavi Bangoria static int test_process_multi_diff_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, diff 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)&b, (__u64)sizeof(b));
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 
test_process_multi_same_addr(void)448c65c64ccSRavi Bangoria static int test_process_multi_same_addr(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, same addr";
453c65c64ccSRavi Bangoria 	size_t res;
454c65c64ccSRavi Bangoria 
455c65c64ccSRavi Bangoria 	fd1 = perf_process_event_open(HW_BREAKPOINT_RW, (__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_RW, (__u64)&a, (__u64)sizeof(a));
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 != 2 || breaks2 != 2) {
485c65c64ccSRavi Bangoria 		printf("FAILED: %s: %lld != 2 || %lld != 2\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 
test_process_multi_diff_addr_ro_wo(void)493c65c64ccSRavi Bangoria static int test_process_multi_diff_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, diff addr, one is RO, other is WO";
498c65c64ccSRavi Bangoria 	size_t res;
499c65c64ccSRavi Bangoria 
500c65c64ccSRavi Bangoria 	fd1 = perf_process_event_open(HW_BREAKPOINT_W, (__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_R, (__u64)&b, (__u64)sizeof(b));
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 
test_process_multi_same_addr_ro_wo(void)538c65c64ccSRavi Bangoria static int test_process_multi_same_addr_ro_wo(void)
539c65c64ccSRavi Bangoria {
540c65c64ccSRavi Bangoria 	unsigned long long breaks1 = 0, breaks2 = 0;
541c65c64ccSRavi Bangoria 	int fd1, fd2;
542c65c64ccSRavi Bangoria 	char *desc = "Process specific, Two events, same addr, one is RO, other is WO";
543c65c64ccSRavi Bangoria 	size_t res;
544c65c64ccSRavi Bangoria 
545c65c64ccSRavi Bangoria 	fd1 = perf_process_event_open(HW_BREAKPOINT_R, (__u64)&a, (__u64)sizeof(a));
546c65c64ccSRavi Bangoria 	if (fd1 < 0) {
547c65c64ccSRavi Bangoria 		perror("perf_process_event_open");
548c65c64ccSRavi Bangoria 		exit(EXIT_FAILURE);
549c65c64ccSRavi Bangoria 	}
550c65c64ccSRavi Bangoria 
551c65c64ccSRavi Bangoria 	fd2 = perf_process_event_open(HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));
552c65c64ccSRavi Bangoria 	if (fd2 < 0) {
553c65c64ccSRavi Bangoria 		close(fd1);
554c65c64ccSRavi Bangoria 		perror("perf_process_event_open");
555c65c64ccSRavi Bangoria 		exit(EXIT_FAILURE);
556c65c64ccSRavi Bangoria 	}
557c65c64ccSRavi Bangoria 
558c65c64ccSRavi Bangoria 	ioctl(fd1, PERF_EVENT_IOC_RESET);
559c65c64ccSRavi Bangoria 	ioctl(fd2, PERF_EVENT_IOC_RESET);
560c65c64ccSRavi Bangoria 	ioctl(fd1, PERF_EVENT_IOC_ENABLE);
561c65c64ccSRavi Bangoria 	ioctl(fd2, PERF_EVENT_IOC_ENABLE);
562c65c64ccSRavi Bangoria 	multi_dawr_workload();
563c65c64ccSRavi Bangoria 	ioctl(fd1, PERF_EVENT_IOC_DISABLE);
564c65c64ccSRavi Bangoria 	ioctl(fd2, PERF_EVENT_IOC_DISABLE);
565c65c64ccSRavi Bangoria 
566c65c64ccSRavi Bangoria 	res = read(fd1, &breaks1, sizeof(breaks1));
567c65c64ccSRavi Bangoria 	assert(res == sizeof(unsigned long long));
568c65c64ccSRavi Bangoria 	res = read(fd2, &breaks2, sizeof(breaks2));
569c65c64ccSRavi Bangoria 	assert(res == sizeof(unsigned long long));
570c65c64ccSRavi Bangoria 
571c65c64ccSRavi Bangoria 	close(fd1);
572c65c64ccSRavi Bangoria 	close(fd2);
573c65c64ccSRavi Bangoria 
574c65c64ccSRavi Bangoria 	if (breaks1 != 1 || breaks2 != 1) {
575c65c64ccSRavi Bangoria 		printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);
576c65c64ccSRavi Bangoria 		return 1;
577c65c64ccSRavi Bangoria 	}
578c65c64ccSRavi Bangoria 
579c65c64ccSRavi Bangoria 	printf("TESTED: %s\n", desc);
580c65c64ccSRavi Bangoria 	return 0;
581c65c64ccSRavi Bangoria }
582c65c64ccSRavi Bangoria 
test_syswide_multi_diff_addr(void)583c65c64ccSRavi Bangoria static int test_syswide_multi_diff_addr(void)
584c65c64ccSRavi Bangoria {
585c65c64ccSRavi Bangoria 	unsigned long long breaks1 = 0, breaks2 = 0;
586c65c64ccSRavi Bangoria 	int *fd1 = malloc(nprocs * sizeof(int));
587c65c64ccSRavi Bangoria 	int *fd2 = malloc(nprocs * sizeof(int));
588c65c64ccSRavi Bangoria 	char *desc = "Systemwide, Two events, diff addr";
589c65c64ccSRavi Bangoria 	int ret;
590c65c64ccSRavi Bangoria 
591c65c64ccSRavi Bangoria 	ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
59271ae6305SNaveen N. Rao 	if (ret)
593c65c64ccSRavi Bangoria 		exit(EXIT_FAILURE);
594c65c64ccSRavi Bangoria 
595c65c64ccSRavi Bangoria 	ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_RW, (__u64)&b, (__u64)sizeof(b));
596c65c64ccSRavi Bangoria 	if (ret) {
597c65c64ccSRavi Bangoria 		close_fds(fd1, nprocs);
598c65c64ccSRavi Bangoria 		exit(EXIT_FAILURE);
599c65c64ccSRavi Bangoria 	}
600c65c64ccSRavi Bangoria 
601c65c64ccSRavi Bangoria 	reset_fds(fd1, nprocs);
602c65c64ccSRavi Bangoria 	reset_fds(fd2, nprocs);
603c65c64ccSRavi Bangoria 	enable_fds(fd1, nprocs);
604c65c64ccSRavi Bangoria 	enable_fds(fd2, nprocs);
605c65c64ccSRavi Bangoria 	multi_dawr_workload();
606c65c64ccSRavi Bangoria 	disable_fds(fd1, nprocs);
607c65c64ccSRavi Bangoria 	disable_fds(fd2, nprocs);
608c65c64ccSRavi Bangoria 
609c65c64ccSRavi Bangoria 	breaks1 = read_fds(fd1, nprocs);
610c65c64ccSRavi Bangoria 	breaks2 = read_fds(fd2, nprocs);
611c65c64ccSRavi Bangoria 
612c65c64ccSRavi Bangoria 	close_fds(fd1, nprocs);
613c65c64ccSRavi Bangoria 	close_fds(fd2, nprocs);
614c65c64ccSRavi Bangoria 
615c65c64ccSRavi Bangoria 	free(fd1);
616c65c64ccSRavi Bangoria 	free(fd2);
617c65c64ccSRavi Bangoria 
618c65c64ccSRavi Bangoria 	if (breaks1 != 2 || breaks2 != 2) {
619c65c64ccSRavi Bangoria 		printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);
620c65c64ccSRavi Bangoria 		return 1;
621c65c64ccSRavi Bangoria 	}
622c65c64ccSRavi Bangoria 
623c65c64ccSRavi Bangoria 	printf("TESTED: %s\n", desc);
624c65c64ccSRavi Bangoria 	return 0;
625c65c64ccSRavi Bangoria }
626c65c64ccSRavi Bangoria 
test_syswide_multi_same_addr(void)627c65c64ccSRavi Bangoria static int test_syswide_multi_same_addr(void)
628c65c64ccSRavi Bangoria {
629c65c64ccSRavi Bangoria 	unsigned long long breaks1 = 0, breaks2 = 0;
630c65c64ccSRavi Bangoria 	int *fd1 = malloc(nprocs * sizeof(int));
631c65c64ccSRavi Bangoria 	int *fd2 = malloc(nprocs * sizeof(int));
632c65c64ccSRavi Bangoria 	char *desc = "Systemwide, Two events, same addr";
633c65c64ccSRavi Bangoria 	int ret;
634c65c64ccSRavi Bangoria 
635c65c64ccSRavi Bangoria 	ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
63671ae6305SNaveen N. Rao 	if (ret)
637c65c64ccSRavi Bangoria 		exit(EXIT_FAILURE);
638c65c64ccSRavi Bangoria 
639c65c64ccSRavi Bangoria 	ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
640c65c64ccSRavi Bangoria 	if (ret) {
641c65c64ccSRavi Bangoria 		close_fds(fd1, nprocs);
642c65c64ccSRavi Bangoria 		exit(EXIT_FAILURE);
643c65c64ccSRavi Bangoria 	}
644c65c64ccSRavi Bangoria 
645c65c64ccSRavi Bangoria 	reset_fds(fd1, nprocs);
646c65c64ccSRavi Bangoria 	reset_fds(fd2, nprocs);
647c65c64ccSRavi Bangoria 	enable_fds(fd1, nprocs);
648c65c64ccSRavi Bangoria 	enable_fds(fd2, nprocs);
649c65c64ccSRavi Bangoria 	multi_dawr_workload();
650c65c64ccSRavi Bangoria 	disable_fds(fd1, nprocs);
651c65c64ccSRavi Bangoria 	disable_fds(fd2, nprocs);
652c65c64ccSRavi Bangoria 
653c65c64ccSRavi Bangoria 	breaks1 = read_fds(fd1, nprocs);
654c65c64ccSRavi Bangoria 	breaks2 = read_fds(fd2, nprocs);
655c65c64ccSRavi Bangoria 
656c65c64ccSRavi Bangoria 	close_fds(fd1, nprocs);
657c65c64ccSRavi Bangoria 	close_fds(fd2, nprocs);
658c65c64ccSRavi Bangoria 
659c65c64ccSRavi Bangoria 	free(fd1);
660c65c64ccSRavi Bangoria 	free(fd2);
661c65c64ccSRavi Bangoria 
662c65c64ccSRavi Bangoria 	if (breaks1 != 2 || breaks2 != 2) {
663c65c64ccSRavi Bangoria 		printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);
664c65c64ccSRavi Bangoria 		return 1;
665c65c64ccSRavi Bangoria 	}
666c65c64ccSRavi Bangoria 
667c65c64ccSRavi Bangoria 	printf("TESTED: %s\n", desc);
668c65c64ccSRavi Bangoria 	return 0;
669c65c64ccSRavi Bangoria }
670c65c64ccSRavi Bangoria 
test_syswide_multi_diff_addr_ro_wo(void)671c65c64ccSRavi Bangoria static int test_syswide_multi_diff_addr_ro_wo(void)
672c65c64ccSRavi Bangoria {
673c65c64ccSRavi Bangoria 	unsigned long long breaks1 = 0, breaks2 = 0;
674c65c64ccSRavi Bangoria 	int *fd1 = malloc(nprocs * sizeof(int));
675c65c64ccSRavi Bangoria 	int *fd2 = malloc(nprocs * sizeof(int));
676c65c64ccSRavi Bangoria 	char *desc = "Systemwide, Two events, diff addr, one is RO, other is WO";
677c65c64ccSRavi Bangoria 	int ret;
678c65c64ccSRavi Bangoria 
679c65c64ccSRavi Bangoria 	ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));
68071ae6305SNaveen N. Rao 	if (ret)
681c65c64ccSRavi Bangoria 		exit(EXIT_FAILURE);
682c65c64ccSRavi Bangoria 
683c65c64ccSRavi Bangoria 	ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_R, (__u64)&b, (__u64)sizeof(b));
684c65c64ccSRavi Bangoria 	if (ret) {
685c65c64ccSRavi Bangoria 		close_fds(fd1, nprocs);
686c65c64ccSRavi Bangoria 		exit(EXIT_FAILURE);
687c65c64ccSRavi Bangoria 	}
688c65c64ccSRavi Bangoria 
689c65c64ccSRavi Bangoria 	reset_fds(fd1, nprocs);
690c65c64ccSRavi Bangoria 	reset_fds(fd2, nprocs);
691c65c64ccSRavi Bangoria 	enable_fds(fd1, nprocs);
692c65c64ccSRavi Bangoria 	enable_fds(fd2, nprocs);
693c65c64ccSRavi Bangoria 	multi_dawr_workload();
694c65c64ccSRavi Bangoria 	disable_fds(fd1, nprocs);
695c65c64ccSRavi Bangoria 	disable_fds(fd2, nprocs);
696c65c64ccSRavi Bangoria 
697c65c64ccSRavi Bangoria 	breaks1 = read_fds(fd1, nprocs);
698c65c64ccSRavi Bangoria 	breaks2 = read_fds(fd2, nprocs);
699c65c64ccSRavi Bangoria 
700c65c64ccSRavi Bangoria 	close_fds(fd1, nprocs);
701c65c64ccSRavi Bangoria 	close_fds(fd2, nprocs);
702c65c64ccSRavi Bangoria 
703c65c64ccSRavi Bangoria 	free(fd1);
704c65c64ccSRavi Bangoria 	free(fd2);
705c65c64ccSRavi Bangoria 
706c65c64ccSRavi Bangoria 	if (breaks1 != 1 || breaks2 != 1) {
707c65c64ccSRavi Bangoria 		printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);
708c65c64ccSRavi Bangoria 		return 1;
709c65c64ccSRavi Bangoria 	}
710c65c64ccSRavi Bangoria 
711c65c64ccSRavi Bangoria 	printf("TESTED: %s\n", desc);
712c65c64ccSRavi Bangoria 	return 0;
713c65c64ccSRavi Bangoria }
714c65c64ccSRavi Bangoria 
test_syswide_multi_same_addr_ro_wo(void)715c65c64ccSRavi Bangoria static int test_syswide_multi_same_addr_ro_wo(void)
716c65c64ccSRavi Bangoria {
717c65c64ccSRavi Bangoria 	unsigned long long breaks1 = 0, breaks2 = 0;
718c65c64ccSRavi Bangoria 	int *fd1 = malloc(nprocs * sizeof(int));
719c65c64ccSRavi Bangoria 	int *fd2 = malloc(nprocs * sizeof(int));
720c65c64ccSRavi Bangoria 	char *desc = "Systemwide, Two events, same addr, one is RO, other is WO";
721c65c64ccSRavi Bangoria 	int ret;
722c65c64ccSRavi Bangoria 
723c65c64ccSRavi Bangoria 	ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));
72471ae6305SNaveen N. Rao 	if (ret)
725c65c64ccSRavi Bangoria 		exit(EXIT_FAILURE);
726c65c64ccSRavi Bangoria 
727c65c64ccSRavi Bangoria 	ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_R, (__u64)&a, (__u64)sizeof(a));
728c65c64ccSRavi Bangoria 	if (ret) {
729c65c64ccSRavi Bangoria 		close_fds(fd1, nprocs);
730c65c64ccSRavi Bangoria 		exit(EXIT_FAILURE);
731c65c64ccSRavi Bangoria 	}
732c65c64ccSRavi Bangoria 
733c65c64ccSRavi Bangoria 	reset_fds(fd1, nprocs);
734c65c64ccSRavi Bangoria 	reset_fds(fd2, nprocs);
735c65c64ccSRavi Bangoria 	enable_fds(fd1, nprocs);
736c65c64ccSRavi Bangoria 	enable_fds(fd2, nprocs);
737c65c64ccSRavi Bangoria 	multi_dawr_workload();
738c65c64ccSRavi Bangoria 	disable_fds(fd1, nprocs);
739c65c64ccSRavi Bangoria 	disable_fds(fd2, nprocs);
740c65c64ccSRavi Bangoria 
741c65c64ccSRavi Bangoria 	breaks1 = read_fds(fd1, nprocs);
742c65c64ccSRavi Bangoria 	breaks2 = read_fds(fd2, nprocs);
743c65c64ccSRavi Bangoria 
744c65c64ccSRavi Bangoria 	close_fds(fd1, nprocs);
745c65c64ccSRavi Bangoria 	close_fds(fd2, nprocs);
746c65c64ccSRavi Bangoria 
747c65c64ccSRavi Bangoria 	free(fd1);
748c65c64ccSRavi Bangoria 	free(fd2);
749c65c64ccSRavi Bangoria 
750c65c64ccSRavi Bangoria 	if (breaks1 != 1 || breaks2 != 1) {
751c65c64ccSRavi Bangoria 		printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);
752c65c64ccSRavi Bangoria 		return 1;
753c65c64ccSRavi Bangoria 	}
754c65c64ccSRavi Bangoria 
755c65c64ccSRavi Bangoria 	printf("TESTED: %s\n", desc);
756c65c64ccSRavi Bangoria 	return 0;
757c65c64ccSRavi Bangoria }
758c65c64ccSRavi Bangoria 
runtest_multi_dawr(void)759c65c64ccSRavi Bangoria static int runtest_multi_dawr(void)
760c65c64ccSRavi Bangoria {
761c65c64ccSRavi Bangoria 	int ret = 0;
762c65c64ccSRavi Bangoria 
763c65c64ccSRavi Bangoria 	ret |= test_process_multi_diff_addr();
764c65c64ccSRavi Bangoria 	ret |= test_process_multi_same_addr();
765c65c64ccSRavi Bangoria 	ret |= test_process_multi_diff_addr_ro_wo();
766c65c64ccSRavi Bangoria 	ret |= test_process_multi_same_addr_ro_wo();
767c65c64ccSRavi Bangoria 	ret |= test_syswide_multi_diff_addr();
768c65c64ccSRavi Bangoria 	ret |= test_syswide_multi_same_addr();
769c65c64ccSRavi Bangoria 	ret |= test_syswide_multi_diff_addr_ro_wo();
770c65c64ccSRavi Bangoria 	ret |= test_syswide_multi_same_addr_ro_wo();
771c65c64ccSRavi Bangoria 
772c65c64ccSRavi Bangoria 	return ret;
773c65c64ccSRavi Bangoria }
774c65c64ccSRavi Bangoria 
runtest_unaligned_512bytes(void)775c65c64ccSRavi Bangoria static int runtest_unaligned_512bytes(void)
776c65c64ccSRavi Bangoria {
777c65c64ccSRavi Bangoria 	unsigned long long breaks = 0;
778c65c64ccSRavi Bangoria 	int fd;
779c65c64ccSRavi Bangoria 	char *desc = "Process specific, 512 bytes, unaligned";
780c65c64ccSRavi Bangoria 	__u64 addr = (__u64)&c + 8;
781c65c64ccSRavi Bangoria 	size_t res;
782c65c64ccSRavi Bangoria 
783c65c64ccSRavi Bangoria 	fd = perf_process_event_open(HW_BREAKPOINT_RW, addr, 512);
784c65c64ccSRavi Bangoria 	if (fd < 0) {
785c65c64ccSRavi Bangoria 		perror("perf_process_event_open");
786c65c64ccSRavi Bangoria 		exit(EXIT_FAILURE);
787c65c64ccSRavi Bangoria 	}
788c65c64ccSRavi Bangoria 
789c65c64ccSRavi Bangoria 	ioctl(fd, PERF_EVENT_IOC_RESET);
790c65c64ccSRavi Bangoria 	ioctl(fd, PERF_EVENT_IOC_ENABLE);
791c65c64ccSRavi Bangoria 	multi_dawr_workload();
792c65c64ccSRavi Bangoria 	ioctl(fd, PERF_EVENT_IOC_DISABLE);
793c65c64ccSRavi Bangoria 
794c65c64ccSRavi Bangoria 	res = read(fd, &breaks, sizeof(breaks));
795c65c64ccSRavi Bangoria 	assert(res == sizeof(unsigned long long));
796c65c64ccSRavi Bangoria 
797c65c64ccSRavi Bangoria 	close(fd);
798c65c64ccSRavi Bangoria 
799c65c64ccSRavi Bangoria 	if (breaks != 2) {
800c65c64ccSRavi Bangoria 		printf("FAILED: %s: %lld != 2\n", desc, breaks);
801c65c64ccSRavi Bangoria 		return 1;
802c65c64ccSRavi Bangoria 	}
803c65c64ccSRavi Bangoria 
804c65c64ccSRavi Bangoria 	printf("TESTED: %s\n", desc);
805c65c64ccSRavi Bangoria 	return 0;
806c65c64ccSRavi Bangoria }
807c65c64ccSRavi Bangoria 
808c65c64ccSRavi Bangoria /* There is no perf api to find number of available watchpoints. Use ptrace. */
get_nr_wps(bool * arch_31)809c65c64ccSRavi Bangoria static int get_nr_wps(bool *arch_31)
810c65c64ccSRavi Bangoria {
811c65c64ccSRavi Bangoria 	struct ppc_debug_info dbginfo;
812c65c64ccSRavi Bangoria 	int child_pid;
813c65c64ccSRavi Bangoria 
814c65c64ccSRavi Bangoria 	child_pid = fork();
815c65c64ccSRavi Bangoria 	if (!child_pid) {
816c65c64ccSRavi Bangoria 		int ret = ptrace(PTRACE_TRACEME, 0, NULL, 0);
817c65c64ccSRavi Bangoria 		if (ret) {
818c65c64ccSRavi Bangoria 			perror("PTRACE_TRACEME failed\n");
819c65c64ccSRavi Bangoria 			exit(EXIT_FAILURE);
820c65c64ccSRavi Bangoria 		}
821c65c64ccSRavi Bangoria 		kill(getpid(), SIGUSR1);
822c65c64ccSRavi Bangoria 
823c65c64ccSRavi Bangoria 		sleep(1);
824c65c64ccSRavi Bangoria 		exit(EXIT_SUCCESS);
825c65c64ccSRavi Bangoria 	}
826c65c64ccSRavi Bangoria 
827c65c64ccSRavi Bangoria 	wait(NULL);
828c65c64ccSRavi Bangoria 	if (ptrace(PPC_PTRACE_GETHWDBGINFO, child_pid, NULL, &dbginfo)) {
829c65c64ccSRavi Bangoria 		perror("Can't get breakpoint info");
830c65c64ccSRavi Bangoria 		exit(EXIT_FAILURE);
831c65c64ccSRavi Bangoria 	}
832c65c64ccSRavi Bangoria 
833c65c64ccSRavi Bangoria 	*arch_31 = !!(dbginfo.features & PPC_DEBUG_FEATURE_DATA_BP_ARCH_31);
834c65c64ccSRavi Bangoria 	return dbginfo.num_data_bps;
835c65c64ccSRavi Bangoria }
836c65c64ccSRavi Bangoria 
runtest(void)8379c2d72d4SMichael Neuling static int runtest(void)
8389c2d72d4SMichael Neuling {
8399c2d72d4SMichael Neuling 	int rwflag;
8409c2d72d4SMichael Neuling 	int exclude_user;
8419c2d72d4SMichael Neuling 	int ret;
842c65c64ccSRavi Bangoria 	bool dawr = dawr_supported();
843c65c64ccSRavi Bangoria 	bool arch_31 = false;
844c65c64ccSRavi Bangoria 	int nr_wps = get_nr_wps(&arch_31);
8459c2d72d4SMichael Neuling 
8469c2d72d4SMichael Neuling 	/*
8479c2d72d4SMichael Neuling 	 * perf defines rwflag as two bits read and write and at least
8489c2d72d4SMichael Neuling 	 * one must be set.  So range 1-3.
8499c2d72d4SMichael Neuling 	 */
8509c2d72d4SMichael Neuling 	for (rwflag = 1 ; rwflag < 4; rwflag++) {
8519c2d72d4SMichael Neuling 		for (exclude_user = 0 ; exclude_user < 2; exclude_user++) {
8529c2d72d4SMichael Neuling 			ret = runtestsingle(rwflag, exclude_user, 0);
8539c2d72d4SMichael Neuling 			if (ret)
8549c2d72d4SMichael Neuling 				return ret;
8559c2d72d4SMichael Neuling 
8569c2d72d4SMichael Neuling 			/* if we have the dawr, we can do an array test */
857c65c64ccSRavi Bangoria 			if (!dawr)
8589c2d72d4SMichael Neuling 				continue;
8599c2d72d4SMichael Neuling 			ret = runtestsingle(rwflag, exclude_user, 1);
8609c2d72d4SMichael Neuling 			if (ret)
8619c2d72d4SMichael Neuling 				return ret;
8629c2d72d4SMichael Neuling 		}
8639c2d72d4SMichael Neuling 	}
864949758a2SRavi Bangoria 
865949758a2SRavi Bangoria 	ret = runtest_dar_outside();
866c65c64ccSRavi Bangoria 	if (ret)
867c65c64ccSRavi Bangoria 		return ret;
868c65c64ccSRavi Bangoria 
869c65c64ccSRavi Bangoria 	if (dawr && nr_wps > 1) {
870c65c64ccSRavi Bangoria 		nprocs = get_nprocs();
871c65c64ccSRavi Bangoria 		ret = runtest_multi_dawr();
872c65c64ccSRavi Bangoria 		if (ret)
873c65c64ccSRavi Bangoria 			return ret;
874c65c64ccSRavi Bangoria 	}
875c65c64ccSRavi Bangoria 
876c65c64ccSRavi Bangoria 	if (dawr && arch_31)
877c65c64ccSRavi Bangoria 		ret = runtest_unaligned_512bytes();
878c65c64ccSRavi Bangoria 
879949758a2SRavi Bangoria 	return ret;
8809c2d72d4SMichael Neuling }
8819c2d72d4SMichael Neuling 
8829c2d72d4SMichael Neuling 
perf_hwbreak(void)8839c2d72d4SMichael Neuling static int perf_hwbreak(void)
8849c2d72d4SMichael Neuling {
8859c2d72d4SMichael Neuling 	srand ( time(NULL) );
8869c2d72d4SMichael Neuling 
887*68877ff2SBenjamin Gray 	SKIP_IF_MSG(!perf_breakpoint_supported(), "Perf breakpoints not supported");
8889c2d72d4SMichael Neuling 
8899c2d72d4SMichael Neuling 	return runtest();
8909c2d72d4SMichael Neuling }
8919c2d72d4SMichael Neuling 
main(int argc,char * argv[],char ** envp)8929c2d72d4SMichael Neuling int main(int argc, char *argv[], char **envp)
8939c2d72d4SMichael Neuling {
8949c2d72d4SMichael Neuling 	return test_harness(perf_hwbreak, "perf_hwbreak");
8959c2d72d4SMichael Neuling }
896