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