cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

perf-hwbreak.c (20604B)


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