brintos

brintos / linux-shallow public Read only

0
0
Text · 20.6 KiB · e374c6b Raw
896 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * perf events self profiling example test case for hw breakpoints.4 *5 * This tests perf PERF_TYPE_BREAKPOINT parameters6 * 1) tests all variants of the break on read/write flags7 * 2) tests exclude_user == 0 and 18 * 3) test array matches (if DAWR is supported))9 * 4) test different numbers of breakpoints matches10 *11 * Configure this breakpoint, then read and write the data a number of12 * times. Then check the output count from perf is as expected.13 *14 * Based on:15 *   http://ozlabs.org/~anton/junkcode/perf_events_example1.c16 *17 * Copyright (C) 2018 Michael Neuling, IBM Corporation.18 */19 20#define _GNU_SOURCE21 22#include <unistd.h>23#include <assert.h>24#include <sched.h>25#include <stdio.h>26#include <stdlib.h>27#include <signal.h>28#include <string.h>29#include <sys/ioctl.h>30#include <sys/wait.h>31#include <sys/ptrace.h>32#include <sys/resource.h>33#include <sys/sysinfo.h>34#include <asm/ptrace.h>35#include <elf.h>36#include <pthread.h>37#include <sys/syscall.h>38#include <linux/perf_event.h>39#include <linux/hw_breakpoint.h>40#include "utils.h"41 42#ifndef PPC_DEBUG_FEATURE_DATA_BP_ARCH_3143#define PPC_DEBUG_FEATURE_DATA_BP_ARCH_31	0x2044#endif45 46#define MAX_LOOPS 1000047 48#define DAWR_LENGTH_MAX ((0x3f + 1) * 8)49 50int nprocs;51 52static volatile int a = 10;53static volatile int b = 10;54static volatile char c[512 + 8] __attribute__((aligned(512)));55 56static void perf_event_attr_set(struct perf_event_attr *attr,57				__u32 type, __u64 addr, __u64 len,58				bool exclude_user)59{60	memset(attr, 0, sizeof(struct perf_event_attr));61	attr->type           = PERF_TYPE_BREAKPOINT;62	attr->size           = sizeof(struct perf_event_attr);63	attr->bp_type        = type;64	attr->bp_addr        = addr;65	attr->bp_len         = len;66	attr->exclude_kernel = 1;67	attr->exclude_hv     = 1;68	attr->exclude_guest  = 1;69	attr->exclude_user   = exclude_user;70	attr->disabled       = 1;71}72 73static int74perf_process_event_open_exclude_user(__u32 type, __u64 addr, __u64 len, bool exclude_user)75{76	struct perf_event_attr attr;77 78	perf_event_attr_set(&attr, type, addr, len, exclude_user);79	return syscall(__NR_perf_event_open, &attr, getpid(), -1, -1, 0);80}81 82static int perf_process_event_open(__u32 type, __u64 addr, __u64 len)83{84	struct perf_event_attr attr;85 86	perf_event_attr_set(&attr, type, addr, len, 0);87	return syscall(__NR_perf_event_open, &attr, getpid(), -1, -1, 0);88}89 90static int perf_cpu_event_open(long cpu, __u32 type, __u64 addr, __u64 len)91{92	struct perf_event_attr attr;93 94	perf_event_attr_set(&attr, type, addr, len, 0);95	return syscall(__NR_perf_event_open, &attr, -1, cpu, -1, 0);96}97 98static void close_fds(int *fd, int n)99{100	int i;101 102	for (i = 0; i < n; i++)103		close(fd[i]);104}105 106static unsigned long read_fds(int *fd, int n)107{108	int i;109	unsigned long c = 0;110	unsigned long count = 0;111	size_t res;112 113	for (i = 0; i < n; i++) {114		res = read(fd[i], &c, sizeof(c));115		assert(res == sizeof(unsigned long long));116		count += c;117	}118	return count;119}120 121static void reset_fds(int *fd, int n)122{123	int i;124 125	for (i = 0; i < n; i++)126		ioctl(fd[i], PERF_EVENT_IOC_RESET);127}128 129static void enable_fds(int *fd, int n)130{131	int i;132 133	for (i = 0; i < n; i++)134		ioctl(fd[i], PERF_EVENT_IOC_ENABLE);135}136 137static void disable_fds(int *fd, int n)138{139	int i;140 141	for (i = 0; i < n; i++)142		ioctl(fd[i], PERF_EVENT_IOC_DISABLE);143}144 145static int perf_systemwide_event_open(int *fd, __u32 type, __u64 addr, __u64 len)146{147	int i, ncpus, cpu, ret = 0;148	struct rlimit rlim;149	cpu_set_t *mask;150	size_t size;151 152	if (getrlimit(RLIMIT_NOFILE, &rlim)) {153		perror("getrlimit");154		return -1;155	}156	rlim.rlim_cur = 65536;157	if (setrlimit(RLIMIT_NOFILE, &rlim)) {158		perror("setrlimit");159		return -1;160	}161 162	ncpus = get_nprocs_conf();163	size = CPU_ALLOC_SIZE(ncpus);164	mask = CPU_ALLOC(ncpus);165	if (!mask) {166		perror("malloc");167		return -1;168	}169 170	CPU_ZERO_S(size, mask);171 172	if (sched_getaffinity(0, size, mask)) {173		perror("sched_getaffinity");174		ret = -1;175		goto done;176	}177 178	for (i = 0, cpu = 0; i < nprocs && cpu < ncpus; cpu++) {179		if (!CPU_ISSET_S(cpu, size, mask))180			continue;181		fd[i] = perf_cpu_event_open(cpu, type, addr, len);182		if (fd[i] < 0) {183			perror("perf_systemwide_event_open");184			close_fds(fd, i);185			ret = fd[i];186			goto done;187		}188		i++;189	}190 191	if (i < nprocs) {192		printf("Error: Number of online cpus reduced since start of test: %d < %d\n", i, nprocs);193		close_fds(fd, i);194		ret = -1;195	}196 197done:198	CPU_FREE(mask);199	return ret;200}201 202static inline bool breakpoint_test(int len)203{204	int fd;205 206	/* bp_addr can point anywhere but needs to be aligned */207	fd = perf_process_event_open(HW_BREAKPOINT_R, (__u64)(&fd) & 0xfffffffffffff800, len);208	if (fd < 0)209		return false;210	close(fd);211	return true;212}213 214static inline bool perf_breakpoint_supported(void)215{216	return breakpoint_test(4);217}218 219static inline bool dawr_supported(void)220{221	return breakpoint_test(DAWR_LENGTH_MAX);222}223 224static int runtestsingle(int readwriteflag, int exclude_user, int arraytest)225{226	int i,j;227	size_t res;228	unsigned long long breaks, needed;229	int readint;230	int readintarraybig[2*DAWR_LENGTH_MAX/sizeof(int)];231	int *readintalign;232	volatile int *ptr;233	int break_fd;234	int loop_num = MAX_LOOPS - (rand() % 100); /* provide some variability */235	volatile int *k;236	__u64 len;237 238	/* align to 0x400 boundary as required by DAWR */239	readintalign = (int *)(((unsigned long)readintarraybig + 0x7ff) &240			       0xfffffffffffff800);241 242	ptr = &readint;243	if (arraytest)244		ptr = &readintalign[0];245 246	len = arraytest ? DAWR_LENGTH_MAX : sizeof(int);247	break_fd = perf_process_event_open_exclude_user(readwriteflag, (__u64)ptr,248							len, exclude_user);249	if (break_fd < 0) {250		perror("perf_process_event_open_exclude_user");251		exit(1);252	}253 254	/* start counters */255	ioctl(break_fd, PERF_EVENT_IOC_ENABLE);256 257	/* Test a bunch of reads and writes */258	k = &readint;259	for (i = 0; i < loop_num; i++) {260		if (arraytest)261			k = &(readintalign[i % (DAWR_LENGTH_MAX/sizeof(int))]);262 263		j = *k;264		*k = j;265	}266 267	/* stop counters */268	ioctl(break_fd, PERF_EVENT_IOC_DISABLE);269 270	/* read and check counters */271	res = read(break_fd, &breaks, sizeof(unsigned long long));272	assert(res == sizeof(unsigned long long));273	/* we read and write each loop, so subtract the ones we are counting */274	needed = 0;275	if (readwriteflag & HW_BREAKPOINT_R)276		needed += loop_num;277	if (readwriteflag & HW_BREAKPOINT_W)278		needed += loop_num;279	needed = needed * (1 - exclude_user);280	printf("TESTED: addr:0x%lx brks:% 8lld loops:% 8i rw:%i !user:%i array:%i\n",281	       (unsigned long int)ptr, breaks, loop_num, readwriteflag, exclude_user, arraytest);282	if (breaks != needed) {283		printf("FAILED: 0x%lx brks:%lld needed:%lli %i %i %i\n\n",284		       (unsigned long int)ptr, breaks, needed, loop_num, readwriteflag, exclude_user);285		return 1;286	}287	close(break_fd);288 289	return 0;290}291 292static int runtest_dar_outside(void)293{294	void *target;295	volatile __u16 temp16;296	volatile __u64 temp64;297	int break_fd;298	unsigned long long breaks;299	int fail = 0;300	size_t res;301 302	target = malloc(8);303	if (!target) {304		perror("malloc failed");305		exit(EXIT_FAILURE);306	}307 308	/* watch middle half of target array */309	break_fd = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)(target + 2), 4);310	if (break_fd < 0) {311		free(target);312		perror("perf_process_event_open");313		exit(EXIT_FAILURE);314	}315 316	/* Shouldn't hit. */317	ioctl(break_fd, PERF_EVENT_IOC_RESET);318	ioctl(break_fd, PERF_EVENT_IOC_ENABLE);319	temp16 = *((__u16 *)target);320	*((__u16 *)target) = temp16;321	ioctl(break_fd, PERF_EVENT_IOC_DISABLE);322	res = read(break_fd, &breaks, sizeof(unsigned long long));323	assert(res == sizeof(unsigned long long));324	if (breaks == 0) {325		printf("TESTED: No overlap\n");326	} else {327		printf("FAILED: No overlap: %lld != 0\n", breaks);328		fail = 1;329	}330 331	/* Hit */332	ioctl(break_fd, PERF_EVENT_IOC_RESET);333	ioctl(break_fd, PERF_EVENT_IOC_ENABLE);334	temp16 = *((__u16 *)(target + 1));335	*((__u16 *)(target + 1)) = temp16;336	ioctl(break_fd, PERF_EVENT_IOC_DISABLE);337	res = read(break_fd, &breaks, sizeof(unsigned long long));338	assert(res == sizeof(unsigned long long));339	if (breaks == 2) {340		printf("TESTED: Partial overlap\n");341	} else {342		printf("FAILED: Partial overlap: %lld != 2\n", breaks);343		fail = 1;344	}345 346	/* Hit */347	ioctl(break_fd, PERF_EVENT_IOC_RESET);348	ioctl(break_fd, PERF_EVENT_IOC_ENABLE);349	temp16 = *((__u16 *)(target + 5));350	*((__u16 *)(target + 5)) = temp16;351	ioctl(break_fd, PERF_EVENT_IOC_DISABLE);352	res = read(break_fd, &breaks, sizeof(unsigned long long));353	assert(res == sizeof(unsigned long long));354	if (breaks == 2) {355		printf("TESTED: Partial overlap\n");356	} else {357		printf("FAILED: Partial overlap: %lld != 2\n", breaks);358		fail = 1;359	}360 361	/* Shouldn't Hit */362	ioctl(break_fd, PERF_EVENT_IOC_RESET);363	ioctl(break_fd, PERF_EVENT_IOC_ENABLE);364	temp16 = *((__u16 *)(target + 6));365	*((__u16 *)(target + 6)) = temp16;366	ioctl(break_fd, PERF_EVENT_IOC_DISABLE);367	res = read(break_fd, &breaks, sizeof(unsigned long long));368	assert(res == sizeof(unsigned long long));369	if (breaks == 0) {370		printf("TESTED: No overlap\n");371	} else {372		printf("FAILED: No overlap: %lld != 0\n", breaks);373		fail = 1;374	}375 376	/* Hit */377	ioctl(break_fd, PERF_EVENT_IOC_RESET);378	ioctl(break_fd, PERF_EVENT_IOC_ENABLE);379	temp64 = *((__u64 *)target);380	*((__u64 *)target) = temp64;381	ioctl(break_fd, PERF_EVENT_IOC_DISABLE);382	res = read(break_fd, &breaks, sizeof(unsigned long long));383	assert(res == sizeof(unsigned long long));384	if (breaks == 2) {385		printf("TESTED: Full overlap\n");386	} else {387		printf("FAILED: Full overlap: %lld != 2\n", breaks);388		fail = 1;389	}390 391	free(target);392	close(break_fd);393	return fail;394}395 396static void multi_dawr_workload(void)397{398	a += 10;399	b += 10;400	c[512 + 1] += 'a';401}402 403static int test_process_multi_diff_addr(void)404{405	unsigned long long breaks1 = 0, breaks2 = 0;406	int fd1, fd2;407	char *desc = "Process specific, Two events, diff addr";408	size_t res;409 410	fd1 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));411	if (fd1 < 0) {412		perror("perf_process_event_open");413		exit(EXIT_FAILURE);414	}415 416	fd2 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&b, (__u64)sizeof(b));417	if (fd2 < 0) {418		close(fd1);419		perror("perf_process_event_open");420		exit(EXIT_FAILURE);421	}422 423	ioctl(fd1, PERF_EVENT_IOC_RESET);424	ioctl(fd2, PERF_EVENT_IOC_RESET);425	ioctl(fd1, PERF_EVENT_IOC_ENABLE);426	ioctl(fd2, PERF_EVENT_IOC_ENABLE);427	multi_dawr_workload();428	ioctl(fd1, PERF_EVENT_IOC_DISABLE);429	ioctl(fd2, PERF_EVENT_IOC_DISABLE);430 431	res = read(fd1, &breaks1, sizeof(breaks1));432	assert(res == sizeof(unsigned long long));433	res = read(fd2, &breaks2, sizeof(breaks2));434	assert(res == sizeof(unsigned long long));435 436	close(fd1);437	close(fd2);438 439	if (breaks1 != 2 || breaks2 != 2) {440		printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);441		return 1;442	}443 444	printf("TESTED: %s\n", desc);445	return 0;446}447 448static int test_process_multi_same_addr(void)449{450	unsigned long long breaks1 = 0, breaks2 = 0;451	int fd1, fd2;452	char *desc = "Process specific, Two events, same addr";453	size_t res;454 455	fd1 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));456	if (fd1 < 0) {457		perror("perf_process_event_open");458		exit(EXIT_FAILURE);459	}460 461	fd2 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));462	if (fd2 < 0) {463		close(fd1);464		perror("perf_process_event_open");465		exit(EXIT_FAILURE);466	}467 468	ioctl(fd1, PERF_EVENT_IOC_RESET);469	ioctl(fd2, PERF_EVENT_IOC_RESET);470	ioctl(fd1, PERF_EVENT_IOC_ENABLE);471	ioctl(fd2, PERF_EVENT_IOC_ENABLE);472	multi_dawr_workload();473	ioctl(fd1, PERF_EVENT_IOC_DISABLE);474	ioctl(fd2, PERF_EVENT_IOC_DISABLE);475 476	res = read(fd1, &breaks1, sizeof(breaks1));477	assert(res == sizeof(unsigned long long));478	res = read(fd2, &breaks2, sizeof(breaks2));479	assert(res == sizeof(unsigned long long));480 481	close(fd1);482	close(fd2);483 484	if (breaks1 != 2 || breaks2 != 2) {485		printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);486		return 1;487	}488 489	printf("TESTED: %s\n", desc);490	return 0;491}492 493static int test_process_multi_diff_addr_ro_wo(void)494{495	unsigned long long breaks1 = 0, breaks2 = 0;496	int fd1, fd2;497	char *desc = "Process specific, Two events, diff addr, one is RO, other is WO";498	size_t res;499 500	fd1 = perf_process_event_open(HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));501	if (fd1 < 0) {502		perror("perf_process_event_open");503		exit(EXIT_FAILURE);504	}505 506	fd2 = perf_process_event_open(HW_BREAKPOINT_R, (__u64)&b, (__u64)sizeof(b));507	if (fd2 < 0) {508		close(fd1);509		perror("perf_process_event_open");510		exit(EXIT_FAILURE);511	}512 513	ioctl(fd1, PERF_EVENT_IOC_RESET);514	ioctl(fd2, PERF_EVENT_IOC_RESET);515	ioctl(fd1, PERF_EVENT_IOC_ENABLE);516	ioctl(fd2, PERF_EVENT_IOC_ENABLE);517	multi_dawr_workload();518	ioctl(fd1, PERF_EVENT_IOC_DISABLE);519	ioctl(fd2, PERF_EVENT_IOC_DISABLE);520 521	res = read(fd1, &breaks1, sizeof(breaks1));522	assert(res == sizeof(unsigned long long));523	res = read(fd2, &breaks2, sizeof(breaks2));524	assert(res == sizeof(unsigned long long));525 526	close(fd1);527	close(fd2);528 529	if (breaks1 != 1 || breaks2 != 1) {530		printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);531		return 1;532	}533 534	printf("TESTED: %s\n", desc);535	return 0;536}537 538static int test_process_multi_same_addr_ro_wo(void)539{540	unsigned long long breaks1 = 0, breaks2 = 0;541	int fd1, fd2;542	char *desc = "Process specific, Two events, same addr, one is RO, other is WO";543	size_t res;544 545	fd1 = perf_process_event_open(HW_BREAKPOINT_R, (__u64)&a, (__u64)sizeof(a));546	if (fd1 < 0) {547		perror("perf_process_event_open");548		exit(EXIT_FAILURE);549	}550 551	fd2 = perf_process_event_open(HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));552	if (fd2 < 0) {553		close(fd1);554		perror("perf_process_event_open");555		exit(EXIT_FAILURE);556	}557 558	ioctl(fd1, PERF_EVENT_IOC_RESET);559	ioctl(fd2, PERF_EVENT_IOC_RESET);560	ioctl(fd1, PERF_EVENT_IOC_ENABLE);561	ioctl(fd2, PERF_EVENT_IOC_ENABLE);562	multi_dawr_workload();563	ioctl(fd1, PERF_EVENT_IOC_DISABLE);564	ioctl(fd2, PERF_EVENT_IOC_DISABLE);565 566	res = read(fd1, &breaks1, sizeof(breaks1));567	assert(res == sizeof(unsigned long long));568	res = read(fd2, &breaks2, sizeof(breaks2));569	assert(res == sizeof(unsigned long long));570 571	close(fd1);572	close(fd2);573 574	if (breaks1 != 1 || breaks2 != 1) {575		printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);576		return 1;577	}578 579	printf("TESTED: %s\n", desc);580	return 0;581}582 583static int test_syswide_multi_diff_addr(void)584{585	unsigned long long breaks1 = 0, breaks2 = 0;586	int *fd1 = malloc(nprocs * sizeof(int));587	int *fd2 = malloc(nprocs * sizeof(int));588	char *desc = "Systemwide, Two events, diff addr";589	int ret;590 591	ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));592	if (ret)593		exit(EXIT_FAILURE);594 595	ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_RW, (__u64)&b, (__u64)sizeof(b));596	if (ret) {597		close_fds(fd1, nprocs);598		exit(EXIT_FAILURE);599	}600 601	reset_fds(fd1, nprocs);602	reset_fds(fd2, nprocs);603	enable_fds(fd1, nprocs);604	enable_fds(fd2, nprocs);605	multi_dawr_workload();606	disable_fds(fd1, nprocs);607	disable_fds(fd2, nprocs);608 609	breaks1 = read_fds(fd1, nprocs);610	breaks2 = read_fds(fd2, nprocs);611 612	close_fds(fd1, nprocs);613	close_fds(fd2, nprocs);614 615	free(fd1);616	free(fd2);617 618	if (breaks1 != 2 || breaks2 != 2) {619		printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);620		return 1;621	}622 623	printf("TESTED: %s\n", desc);624	return 0;625}626 627static int test_syswide_multi_same_addr(void)628{629	unsigned long long breaks1 = 0, breaks2 = 0;630	int *fd1 = malloc(nprocs * sizeof(int));631	int *fd2 = malloc(nprocs * sizeof(int));632	char *desc = "Systemwide, Two events, same addr";633	int ret;634 635	ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));636	if (ret)637		exit(EXIT_FAILURE);638 639	ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));640	if (ret) {641		close_fds(fd1, nprocs);642		exit(EXIT_FAILURE);643	}644 645	reset_fds(fd1, nprocs);646	reset_fds(fd2, nprocs);647	enable_fds(fd1, nprocs);648	enable_fds(fd2, nprocs);649	multi_dawr_workload();650	disable_fds(fd1, nprocs);651	disable_fds(fd2, nprocs);652 653	breaks1 = read_fds(fd1, nprocs);654	breaks2 = read_fds(fd2, nprocs);655 656	close_fds(fd1, nprocs);657	close_fds(fd2, nprocs);658 659	free(fd1);660	free(fd2);661 662	if (breaks1 != 2 || breaks2 != 2) {663		printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);664		return 1;665	}666 667	printf("TESTED: %s\n", desc);668	return 0;669}670 671static int test_syswide_multi_diff_addr_ro_wo(void)672{673	unsigned long long breaks1 = 0, breaks2 = 0;674	int *fd1 = malloc(nprocs * sizeof(int));675	int *fd2 = malloc(nprocs * sizeof(int));676	char *desc = "Systemwide, Two events, diff addr, one is RO, other is WO";677	int ret;678 679	ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));680	if (ret)681		exit(EXIT_FAILURE);682 683	ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_R, (__u64)&b, (__u64)sizeof(b));684	if (ret) {685		close_fds(fd1, nprocs);686		exit(EXIT_FAILURE);687	}688 689	reset_fds(fd1, nprocs);690	reset_fds(fd2, nprocs);691	enable_fds(fd1, nprocs);692	enable_fds(fd2, nprocs);693	multi_dawr_workload();694	disable_fds(fd1, nprocs);695	disable_fds(fd2, nprocs);696 697	breaks1 = read_fds(fd1, nprocs);698	breaks2 = read_fds(fd2, nprocs);699 700	close_fds(fd1, nprocs);701	close_fds(fd2, nprocs);702 703	free(fd1);704	free(fd2);705 706	if (breaks1 != 1 || breaks2 != 1) {707		printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);708		return 1;709	}710 711	printf("TESTED: %s\n", desc);712	return 0;713}714 715static int test_syswide_multi_same_addr_ro_wo(void)716{717	unsigned long long breaks1 = 0, breaks2 = 0;718	int *fd1 = malloc(nprocs * sizeof(int));719	int *fd2 = malloc(nprocs * sizeof(int));720	char *desc = "Systemwide, Two events, same addr, one is RO, other is WO";721	int ret;722 723	ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));724	if (ret)725		exit(EXIT_FAILURE);726 727	ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_R, (__u64)&a, (__u64)sizeof(a));728	if (ret) {729		close_fds(fd1, nprocs);730		exit(EXIT_FAILURE);731	}732 733	reset_fds(fd1, nprocs);734	reset_fds(fd2, nprocs);735	enable_fds(fd1, nprocs);736	enable_fds(fd2, nprocs);737	multi_dawr_workload();738	disable_fds(fd1, nprocs);739	disable_fds(fd2, nprocs);740 741	breaks1 = read_fds(fd1, nprocs);742	breaks2 = read_fds(fd2, nprocs);743 744	close_fds(fd1, nprocs);745	close_fds(fd2, nprocs);746 747	free(fd1);748	free(fd2);749 750	if (breaks1 != 1 || breaks2 != 1) {751		printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);752		return 1;753	}754 755	printf("TESTED: %s\n", desc);756	return 0;757}758 759static int runtest_multi_dawr(void)760{761	int ret = 0;762 763	ret |= test_process_multi_diff_addr();764	ret |= test_process_multi_same_addr();765	ret |= test_process_multi_diff_addr_ro_wo();766	ret |= test_process_multi_same_addr_ro_wo();767	ret |= test_syswide_multi_diff_addr();768	ret |= test_syswide_multi_same_addr();769	ret |= test_syswide_multi_diff_addr_ro_wo();770	ret |= test_syswide_multi_same_addr_ro_wo();771 772	return ret;773}774 775static int runtest_unaligned_512bytes(void)776{777	unsigned long long breaks = 0;778	int fd;779	char *desc = "Process specific, 512 bytes, unaligned";780	__u64 addr = (__u64)&c + 8;781	size_t res;782 783	fd = perf_process_event_open(HW_BREAKPOINT_RW, addr, 512);784	if (fd < 0) {785		perror("perf_process_event_open");786		exit(EXIT_FAILURE);787	}788 789	ioctl(fd, PERF_EVENT_IOC_RESET);790	ioctl(fd, PERF_EVENT_IOC_ENABLE);791	multi_dawr_workload();792	ioctl(fd, PERF_EVENT_IOC_DISABLE);793 794	res = read(fd, &breaks, sizeof(breaks));795	assert(res == sizeof(unsigned long long));796 797	close(fd);798 799	if (breaks != 2) {800		printf("FAILED: %s: %lld != 2\n", desc, breaks);801		return 1;802	}803 804	printf("TESTED: %s\n", desc);805	return 0;806}807 808/* There is no perf api to find number of available watchpoints. Use ptrace. */809static int get_nr_wps(bool *arch_31)810{811	struct ppc_debug_info dbginfo;812	int child_pid;813 814	child_pid = fork();815	if (!child_pid) {816		int ret = ptrace(PTRACE_TRACEME, 0, NULL, 0);817		if (ret) {818			perror("PTRACE_TRACEME failed\n");819			exit(EXIT_FAILURE);820		}821		kill(getpid(), SIGUSR1);822 823		sleep(1);824		exit(EXIT_SUCCESS);825	}826 827	wait(NULL);828	if (ptrace(PPC_PTRACE_GETHWDBGINFO, child_pid, NULL, &dbginfo)) {829		perror("Can't get breakpoint info");830		exit(EXIT_FAILURE);831	}832 833	*arch_31 = !!(dbginfo.features & PPC_DEBUG_FEATURE_DATA_BP_ARCH_31);834	return dbginfo.num_data_bps;835}836 837static int runtest(void)838{839	int rwflag;840	int exclude_user;841	int ret;842	bool dawr = dawr_supported();843	bool arch_31 = false;844	int nr_wps = get_nr_wps(&arch_31);845 846	/*847	 * perf defines rwflag as two bits read and write and at least848	 * one must be set.  So range 1-3.849	 */850	for (rwflag = 1 ; rwflag < 4; rwflag++) {851		for (exclude_user = 0 ; exclude_user < 2; exclude_user++) {852			ret = runtestsingle(rwflag, exclude_user, 0);853			if (ret)854				return ret;855 856			/* if we have the dawr, we can do an array test */857			if (!dawr)858				continue;859			ret = runtestsingle(rwflag, exclude_user, 1);860			if (ret)861				return ret;862		}863	}864 865	ret = runtest_dar_outside();866	if (ret)867		return ret;868 869	if (dawr && nr_wps > 1) {870		nprocs = get_nprocs();871		ret = runtest_multi_dawr();872		if (ret)873			return ret;874	}875 876	if (dawr && arch_31)877		ret = runtest_unaligned_512bytes();878 879	return ret;880}881 882 883static int perf_hwbreak(void)884{885	srand ( time(NULL) );886 887	SKIP_IF_MSG(!perf_breakpoint_supported(), "Perf breakpoints not supported");888 889	return runtest();890}891 892int main(int argc, char *argv[], char **envp)893{894	return test_harness(perf_hwbreak, "perf_hwbreak");895}896