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}