~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/powerpc/ptrace/perf-hwbreak.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 #define _GNU_SOURCE
 21 
 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_31
 43 #define PPC_DEBUG_FEATURE_DATA_BP_ARCH_31       0x20
 44 #endif
 45 
 46 #define MAX_LOOPS 10000
 47 
 48 #define DAWR_LENGTH_MAX ((0x3f + 1) * 8)
 49 
 50 int nprocs;
 51 
 52 static volatile int a = 10;
 53 static volatile int b = 10;
 54 static volatile char c[512 + 8] __attribute__((aligned(512)));
 55 
 56 static 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 
 73 static int
 74 perf_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 
 82 static 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 
 90 static 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 
 98 static 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 
106 static 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 
121 static 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 
129 static 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 
137 static 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 
145 static 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 
197 done:
198         CPU_FREE(mask);
199         return ret;
200 }
201 
202 static 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 
214 static inline bool perf_breakpoint_supported(void)
215 {
216         return breakpoint_test(4);
217 }
218 
219 static inline bool dawr_supported(void)
220 {
221         return breakpoint_test(DAWR_LENGTH_MAX);
222 }
223 
224 static 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 
292 static 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 
396 static void multi_dawr_workload(void)
397 {
398         a += 10;
399         b += 10;
400         c[512 + 1] += 'a';
401 }
402 
403 static 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 
448 static 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 
493 static 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 
538 static 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 
583 static 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 
627 static 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 
671 static 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 
715 static 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 
759 static 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 
775 static 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. */
809 static 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 
837 static 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 least
848          * 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 
883 static 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 
892 int main(int argc, char *argv[], char **envp)
893 {
894         return test_harness(perf_hwbreak, "perf_hwbreak");
895 }
896 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php