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
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.