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