1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * perf events self profiling example test case for hw breakpoints.
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
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.
15 * http://ozlabs.org/~anton/junkcode/perf_events_example1.c
17 * Copyright (C) 2018 Michael Neuling, IBM Corporation.
29 #include <sys/ioctl.h>
31 #include <sys/ptrace.h>
32 #include <sys/resource.h>
33 #include <sys/sysinfo.h>
34 #include <asm/ptrace.h>
37 #include <sys/syscall.h>
38 #include <linux/perf_event.h>
39 #include <linux/hw_breakpoint.h>
42 #ifndef PPC_DEBUG_FEATURE_DATA_BP_ARCH_31
43 #define PPC_DEBUG_FEATURE_DATA_BP_ARCH_31 0x20
46 #define MAX_LOOPS 10000
48 #define DAWR_LENGTH_MAX ((0x3f + 1) * 8)
52 static volatile int a = 10;
53 static volatile int b = 10;
54 static volatile char c[512 + 8] __attribute__((aligned(512)));
56 static void perf_event_attr_set(struct perf_event_attr *attr,
57 __u32 type, __u64 addr, __u64 len,
60 memset(attr, 0, sizeof(struct perf_event_attr));
61 attr->type = PERF_TYPE_BREAKPOINT;
62 attr->size = sizeof(struct perf_event_attr);
66 attr->exclude_kernel = 1;
68 attr->exclude_guest = 1;
69 attr->exclude_user = exclude_user;
74 perf_process_event_open_exclude_user(__u32 type, __u64 addr, __u64 len, bool exclude_user)
76 struct perf_event_attr attr;
78 perf_event_attr_set(&attr, type, addr, len, exclude_user);
79 return syscall(__NR_perf_event_open, &attr, getpid(), -1, -1, 0);
82 static int perf_process_event_open(__u32 type, __u64 addr, __u64 len)
84 struct perf_event_attr attr;
86 perf_event_attr_set(&attr, type, addr, len, 0);
87 return syscall(__NR_perf_event_open, &attr, getpid(), -1, -1, 0);
90 static int perf_cpu_event_open(long cpu, __u32 type, __u64 addr, __u64 len)
92 struct perf_event_attr attr;
94 perf_event_attr_set(&attr, type, addr, len, 0);
95 return syscall(__NR_perf_event_open, &attr, -1, cpu, -1, 0);
98 static void close_fds(int *fd, int n)
102 for (i = 0; i < n; i++)
106 static unsigned long read_fds(int *fd, int n)
110 unsigned long count = 0;
113 for (i = 0; i < n; i++) {
114 res = read(fd[i], &c, sizeof(c));
115 assert(res == sizeof(unsigned long long));
121 static void reset_fds(int *fd, int n)
125 for (i = 0; i < n; i++)
126 ioctl(fd[i], PERF_EVENT_IOC_RESET);
129 static void enable_fds(int *fd, int n)
133 for (i = 0; i < n; i++)
134 ioctl(fd[i], PERF_EVENT_IOC_ENABLE);
137 static void disable_fds(int *fd, int n)
141 for (i = 0; i < n; i++)
142 ioctl(fd[i], PERF_EVENT_IOC_DISABLE);
145 static int perf_systemwide_event_open(int *fd, __u32 type, __u64 addr, __u64 len)
147 int i, ncpus, cpu, ret = 0;
152 if (getrlimit(RLIMIT_NOFILE, &rlim)) {
156 rlim.rlim_cur = 65536;
157 if (setrlimit(RLIMIT_NOFILE, &rlim)) {
162 ncpus = get_nprocs_conf();
163 size = CPU_ALLOC_SIZE(ncpus);
164 mask = CPU_ALLOC(ncpus);
170 CPU_ZERO_S(size, mask);
172 if (sched_getaffinity(0, size, mask)) {
173 perror("sched_getaffinity");
178 for (i = 0, cpu = 0; i < nprocs && cpu < ncpus; cpu++) {
179 if (!CPU_ISSET_S(cpu, size, mask))
181 fd[i] = perf_cpu_event_open(cpu, type, addr, len);
183 perror("perf_systemwide_event_open");
192 printf("Error: Number of online cpus reduced since start of test: %d < %d\n", i, nprocs);
202 static inline bool breakpoint_test(int len)
206 /* bp_addr can point anywhere but needs to be aligned */
207 fd = perf_process_event_open(HW_BREAKPOINT_R, (__u64)(&fd) & 0xfffffffffffff800, len);
214 static inline bool perf_breakpoint_supported(void)
216 return breakpoint_test(4);
219 static inline bool dawr_supported(void)
221 return breakpoint_test(DAWR_LENGTH_MAX);
224 static int runtestsingle(int readwriteflag, int exclude_user, int arraytest)
228 unsigned long long breaks, needed;
230 int readintarraybig[2*DAWR_LENGTH_MAX/sizeof(int)];
234 int loop_num = MAX_LOOPS - (rand() % 100); /* provide some variability */
238 /* align to 0x400 boundary as required by DAWR */
239 readintalign = (int *)(((unsigned long)readintarraybig + 0x7ff) &
244 ptr = &readintalign[0];
246 len = arraytest ? DAWR_LENGTH_MAX : sizeof(int);
247 break_fd = perf_process_event_open_exclude_user(readwriteflag, (__u64)ptr,
250 perror("perf_process_event_open_exclude_user");
255 ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
257 /* Test a bunch of reads and writes */
259 for (i = 0; i < loop_num; i++) {
261 k = &(readintalign[i % (DAWR_LENGTH_MAX/sizeof(int))]);
268 ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
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 */
275 if (readwriteflag & HW_BREAKPOINT_R)
277 if (readwriteflag & HW_BREAKPOINT_W)
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);
292 static int runtest_dar_outside(void)
295 volatile __u16 temp16;
296 volatile __u64 temp64;
298 unsigned long long breaks;
304 perror("malloc failed");
308 /* watch middle half of target array */
309 break_fd = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)(target + 2), 4);
312 perror("perf_process_event_open");
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));
325 printf("TESTED: No overlap\n");
327 printf("FAILED: No overlap: %lld != 0\n", breaks);
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));
340 printf("TESTED: Partial overlap\n");
342 printf("FAILED: Partial overlap: %lld != 2\n", breaks);
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));
355 printf("TESTED: Partial overlap\n");
357 printf("FAILED: Partial overlap: %lld != 2\n", breaks);
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));
370 printf("TESTED: No overlap\n");
372 printf("FAILED: No overlap: %lld != 0\n", breaks);
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));
385 printf("TESTED: Full overlap\n");
387 printf("FAILED: Full overlap: %lld != 2\n", breaks);
396 static void multi_dawr_workload(void)
403 static int test_process_multi_diff_addr(void)
405 unsigned long long breaks1 = 0, breaks2 = 0;
407 char *desc = "Process specific, Two events, diff addr";
410 fd1 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
412 perror("perf_process_event_open");
416 fd2 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&b, (__u64)sizeof(b));
419 perror("perf_process_event_open");
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);
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));
439 if (breaks1 != 2 || breaks2 != 2) {
440 printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);
444 printf("TESTED: %s\n", desc);
448 static int test_process_multi_same_addr(void)
450 unsigned long long breaks1 = 0, breaks2 = 0;
452 char *desc = "Process specific, Two events, same addr";
455 fd1 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
457 perror("perf_process_event_open");
461 fd2 = perf_process_event_open(HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
464 perror("perf_process_event_open");
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);
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));
484 if (breaks1 != 2 || breaks2 != 2) {
485 printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);
489 printf("TESTED: %s\n", desc);
493 static int test_process_multi_diff_addr_ro_wo(void)
495 unsigned long long breaks1 = 0, breaks2 = 0;
497 char *desc = "Process specific, Two events, diff addr, one is RO, other is WO";
500 fd1 = perf_process_event_open(HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));
502 perror("perf_process_event_open");
506 fd2 = perf_process_event_open(HW_BREAKPOINT_R, (__u64)&b, (__u64)sizeof(b));
509 perror("perf_process_event_open");
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);
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));
529 if (breaks1 != 1 || breaks2 != 1) {
530 printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);
534 printf("TESTED: %s\n", desc);
538 static int test_process_multi_same_addr_ro_wo(void)
540 unsigned long long breaks1 = 0, breaks2 = 0;
542 char *desc = "Process specific, Two events, same addr, one is RO, other is WO";
545 fd1 = perf_process_event_open(HW_BREAKPOINT_R, (__u64)&a, (__u64)sizeof(a));
547 perror("perf_process_event_open");
551 fd2 = perf_process_event_open(HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));
554 perror("perf_process_event_open");
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);
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));
574 if (breaks1 != 1 || breaks2 != 1) {
575 printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);
579 printf("TESTED: %s\n", desc);
583 static int test_syswide_multi_diff_addr(void)
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";
591 ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
595 ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_RW, (__u64)&b, (__u64)sizeof(b));
597 close_fds(fd1, nprocs);
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);
609 breaks1 = read_fds(fd1, nprocs);
610 breaks2 = read_fds(fd2, nprocs);
612 close_fds(fd1, nprocs);
613 close_fds(fd2, nprocs);
618 if (breaks1 != 2 || breaks2 != 2) {
619 printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);
623 printf("TESTED: %s\n", desc);
627 static int test_syswide_multi_same_addr(void)
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";
635 ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
639 ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_RW, (__u64)&a, (__u64)sizeof(a));
641 close_fds(fd1, nprocs);
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);
653 breaks1 = read_fds(fd1, nprocs);
654 breaks2 = read_fds(fd2, nprocs);
656 close_fds(fd1, nprocs);
657 close_fds(fd2, nprocs);
662 if (breaks1 != 2 || breaks2 != 2) {
663 printf("FAILED: %s: %lld != 2 || %lld != 2\n", desc, breaks1, breaks2);
667 printf("TESTED: %s\n", desc);
671 static int test_syswide_multi_diff_addr_ro_wo(void)
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";
679 ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));
683 ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_R, (__u64)&b, (__u64)sizeof(b));
685 close_fds(fd1, nprocs);
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);
697 breaks1 = read_fds(fd1, nprocs);
698 breaks2 = read_fds(fd2, nprocs);
700 close_fds(fd1, nprocs);
701 close_fds(fd2, nprocs);
706 if (breaks1 != 1 || breaks2 != 1) {
707 printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);
711 printf("TESTED: %s\n", desc);
715 static int test_syswide_multi_same_addr_ro_wo(void)
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";
723 ret = perf_systemwide_event_open(fd1, HW_BREAKPOINT_W, (__u64)&a, (__u64)sizeof(a));
727 ret = perf_systemwide_event_open(fd2, HW_BREAKPOINT_R, (__u64)&a, (__u64)sizeof(a));
729 close_fds(fd1, nprocs);
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);
741 breaks1 = read_fds(fd1, nprocs);
742 breaks2 = read_fds(fd2, nprocs);
744 close_fds(fd1, nprocs);
745 close_fds(fd2, nprocs);
750 if (breaks1 != 1 || breaks2 != 1) {
751 printf("FAILED: %s: %lld != 1 || %lld != 1\n", desc, breaks1, breaks2);
755 printf("TESTED: %s\n", desc);
759 static int runtest_multi_dawr(void)
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();
775 static int runtest_unaligned_512bytes(void)
777 unsigned long long breaks = 0;
779 char *desc = "Process specific, 512 bytes, unaligned";
780 __u64 addr = (__u64)&c + 8;
783 fd = perf_process_event_open(HW_BREAKPOINT_RW, addr, 512);
785 perror("perf_process_event_open");
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);
794 res = read(fd, &breaks, sizeof(breaks));
795 assert(res == sizeof(unsigned long long));
800 printf("FAILED: %s: %lld != 2\n", desc, breaks);
804 printf("TESTED: %s\n", desc);
808 /* There is no perf api to find number of available watchpoints. Use ptrace. */
809 static int get_nr_wps(bool *arch_31)
811 struct ppc_debug_info dbginfo;
816 int ret = ptrace(PTRACE_TRACEME, 0, NULL, 0);
818 perror("PTRACE_TRACEME failed\n");
821 kill(getpid(), SIGUSR1);
828 if (ptrace(PPC_PTRACE_GETHWDBGINFO, child_pid, NULL, &dbginfo)) {
829 perror("Can't get breakpoint info");
833 *arch_31 = !!(dbginfo.features & PPC_DEBUG_FEATURE_DATA_BP_ARCH_31);
834 return dbginfo.num_data_bps;
837 static int runtest(void)
842 bool dawr = dawr_supported();
843 bool arch_31 = false;
844 int nr_wps = get_nr_wps(&arch_31);
847 * perf defines rwflag as two bits read and write and at least
848 * one must be set. So range 1-3.
850 for (rwflag = 1 ; rwflag < 4; rwflag++) {
851 for (exclude_user = 0 ; exclude_user < 2; exclude_user++) {
852 ret = runtestsingle(rwflag, exclude_user, 0);
856 /* if we have the dawr, we can do an array test */
859 ret = runtestsingle(rwflag, exclude_user, 1);
865 ret = runtest_dar_outside();
869 if (dawr && nr_wps > 1) {
870 nprocs = get_nprocs();
871 ret = runtest_multi_dawr();
877 ret = runtest_unaligned_512bytes();
883 static int perf_hwbreak(void)
885 srand ( time(NULL) );
887 SKIP_IF(!perf_breakpoint_supported());
892 int main(int argc, char *argv[], char **envp)
894 return test_harness(perf_hwbreak, "perf_hwbreak");