1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * Ptrace interface test helper functions 4 * 5 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. 6 */ 7 #include <inttypes.h> 8 #include <unistd.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <malloc.h> 12 #include <errno.h> 13 #include <time.h> 14 #include <sys/ptrace.h> 15 #include <sys/ioctl.h> 16 #include <sys/uio.h> 17 #include <sys/types.h> 18 #include <sys/wait.h> 19 #include <sys/signal.h> 20 #include <sys/ipc.h> 21 #include <sys/shm.h> 22 #include <sys/user.h> 23 #include <linux/elf.h> 24 #include <linux/types.h> 25 #include <linux/auxvec.h> 26 #include "reg.h" 27 #include "utils.h" 28 29 #define TEST_PASS 0 30 #define TEST_FAIL 1 31 32 struct fpr_regs { 33 unsigned long fpr[32]; 34 unsigned long fpscr; 35 }; 36 37 struct tm_spr_regs { 38 unsigned long tm_tfhar; 39 unsigned long tm_texasr; 40 unsigned long tm_tfiar; 41 }; 42 43 #ifndef NT_PPC_TAR 44 #define NT_PPC_TAR 0x103 45 #define NT_PPC_PPR 0x104 46 #define NT_PPC_DSCR 0x105 47 #define NT_PPC_EBB 0x106 48 #define NT_PPC_PMU 0x107 49 #define NT_PPC_TM_CGPR 0x108 50 #define NT_PPC_TM_CFPR 0x109 51 #define NT_PPC_TM_CVMX 0x10a 52 #define NT_PPC_TM_CVSX 0x10b 53 #define NT_PPC_TM_SPR 0x10c 54 #define NT_PPC_TM_CTAR 0x10d 55 #define NT_PPC_TM_CPPR 0x10e 56 #define NT_PPC_TM_CDSCR 0x10f 57 #endif 58 59 /* Basic ptrace operations */ 60 int start_trace(pid_t child) 61 { 62 int ret; 63 64 ret = ptrace(PTRACE_ATTACH, child, NULL, NULL); 65 if (ret) { 66 perror("ptrace(PTRACE_ATTACH) failed"); 67 return TEST_FAIL; 68 } 69 ret = waitpid(child, NULL, 0); 70 if (ret != child) { 71 perror("waitpid() failed"); 72 return TEST_FAIL; 73 } 74 return TEST_PASS; 75 } 76 77 int stop_trace(pid_t child) 78 { 79 int ret; 80 81 ret = ptrace(PTRACE_DETACH, child, NULL, NULL); 82 if (ret) { 83 perror("ptrace(PTRACE_DETACH) failed"); 84 return TEST_FAIL; 85 } 86 return TEST_PASS; 87 } 88 89 int cont_trace(pid_t child) 90 { 91 int ret; 92 93 ret = ptrace(PTRACE_CONT, child, NULL, NULL); 94 if (ret) { 95 perror("ptrace(PTRACE_CONT) failed"); 96 return TEST_FAIL; 97 } 98 return TEST_PASS; 99 } 100 101 int ptrace_read_regs(pid_t child, unsigned long type, unsigned long regs[], 102 int n) 103 { 104 struct iovec iov; 105 long ret; 106 107 FAIL_IF(start_trace(child)); 108 109 iov.iov_base = regs; 110 iov.iov_len = n * sizeof(unsigned long); 111 112 ret = ptrace(PTRACE_GETREGSET, child, type, &iov); 113 if (ret) 114 return ret; 115 116 FAIL_IF(stop_trace(child)); 117 118 return TEST_PASS; 119 } 120 121 long ptrace_write_regs(pid_t child, unsigned long type, unsigned long regs[], 122 int n) 123 { 124 struct iovec iov; 125 long ret; 126 127 FAIL_IF(start_trace(child)); 128 129 iov.iov_base = regs; 130 iov.iov_len = n * sizeof(unsigned long); 131 132 ret = ptrace(PTRACE_SETREGSET, child, type, &iov); 133 134 FAIL_IF(stop_trace(child)); 135 136 return ret; 137 } 138 139 /* TAR, PPR, DSCR */ 140 int show_tar_registers(pid_t child, unsigned long *out) 141 { 142 struct iovec iov; 143 unsigned long *reg; 144 int ret; 145 146 reg = malloc(sizeof(unsigned long)); 147 if (!reg) { 148 perror("malloc() failed"); 149 return TEST_FAIL; 150 } 151 iov.iov_base = (u64 *) reg; 152 iov.iov_len = sizeof(unsigned long); 153 154 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TAR, &iov); 155 if (ret) { 156 perror("ptrace(PTRACE_GETREGSET) failed"); 157 goto fail; 158 } 159 if (out) 160 out[0] = *reg; 161 162 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_PPR, &iov); 163 if (ret) { 164 perror("ptrace(PTRACE_GETREGSET) failed"); 165 goto fail; 166 } 167 if (out) 168 out[1] = *reg; 169 170 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_DSCR, &iov); 171 if (ret) { 172 perror("ptrace(PTRACE_GETREGSET) failed"); 173 goto fail; 174 } 175 if (out) 176 out[2] = *reg; 177 178 free(reg); 179 return TEST_PASS; 180 fail: 181 free(reg); 182 return TEST_FAIL; 183 } 184 185 int write_tar_registers(pid_t child, unsigned long tar, 186 unsigned long ppr, unsigned long dscr) 187 { 188 struct iovec iov; 189 unsigned long *reg; 190 int ret; 191 192 reg = malloc(sizeof(unsigned long)); 193 if (!reg) { 194 perror("malloc() failed"); 195 return TEST_FAIL; 196 } 197 198 iov.iov_base = (u64 *) reg; 199 iov.iov_len = sizeof(unsigned long); 200 201 *reg = tar; 202 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TAR, &iov); 203 if (ret) { 204 perror("ptrace(PTRACE_SETREGSET) failed"); 205 goto fail; 206 } 207 208 *reg = ppr; 209 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_PPR, &iov); 210 if (ret) { 211 perror("ptrace(PTRACE_SETREGSET) failed"); 212 goto fail; 213 } 214 215 *reg = dscr; 216 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_DSCR, &iov); 217 if (ret) { 218 perror("ptrace(PTRACE_SETREGSET) failed"); 219 goto fail; 220 } 221 222 free(reg); 223 return TEST_PASS; 224 fail: 225 free(reg); 226 return TEST_FAIL; 227 } 228 229 int show_tm_checkpointed_state(pid_t child, unsigned long *out) 230 { 231 struct iovec iov; 232 unsigned long *reg; 233 int ret; 234 235 reg = malloc(sizeof(unsigned long)); 236 if (!reg) { 237 perror("malloc() failed"); 238 return TEST_FAIL; 239 } 240 241 iov.iov_base = (u64 *) reg; 242 iov.iov_len = sizeof(unsigned long); 243 244 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CTAR, &iov); 245 if (ret) { 246 perror("ptrace(PTRACE_GETREGSET) failed"); 247 goto fail; 248 } 249 if (out) 250 out[0] = *reg; 251 252 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CPPR, &iov); 253 if (ret) { 254 perror("ptrace(PTRACE_GETREGSET) failed"); 255 goto fail; 256 } 257 if (out) 258 out[1] = *reg; 259 260 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CDSCR, &iov); 261 if (ret) { 262 perror("ptrace(PTRACE_GETREGSET) failed"); 263 goto fail; 264 } 265 if (out) 266 out[2] = *reg; 267 268 free(reg); 269 return TEST_PASS; 270 271 fail: 272 free(reg); 273 return TEST_FAIL; 274 } 275 276 int write_ckpt_tar_registers(pid_t child, unsigned long tar, 277 unsigned long ppr, unsigned long dscr) 278 { 279 struct iovec iov; 280 unsigned long *reg; 281 int ret; 282 283 reg = malloc(sizeof(unsigned long)); 284 if (!reg) { 285 perror("malloc() failed"); 286 return TEST_FAIL; 287 } 288 289 iov.iov_base = (u64 *) reg; 290 iov.iov_len = sizeof(unsigned long); 291 292 *reg = tar; 293 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CTAR, &iov); 294 if (ret) { 295 perror("ptrace(PTRACE_GETREGSET) failed"); 296 goto fail; 297 } 298 299 *reg = ppr; 300 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CPPR, &iov); 301 if (ret) { 302 perror("ptrace(PTRACE_GETREGSET) failed"); 303 goto fail; 304 } 305 306 *reg = dscr; 307 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CDSCR, &iov); 308 if (ret) { 309 perror("ptrace(PTRACE_GETREGSET) failed"); 310 goto fail; 311 } 312 313 free(reg); 314 return TEST_PASS; 315 fail: 316 free(reg); 317 return TEST_FAIL; 318 } 319 320 /* FPR */ 321 int show_fpr(pid_t child, unsigned long *fpr) 322 { 323 struct fpr_regs *regs; 324 int ret, i; 325 326 regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs)); 327 ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs); 328 if (ret) { 329 perror("ptrace(PTRACE_GETREGSET) failed"); 330 return TEST_FAIL; 331 } 332 333 if (fpr) { 334 for (i = 0; i < 32; i++) 335 fpr[i] = regs->fpr[i]; 336 } 337 return TEST_PASS; 338 } 339 340 int write_fpr(pid_t child, unsigned long val) 341 { 342 struct fpr_regs *regs; 343 int ret, i; 344 345 regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs)); 346 ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs); 347 if (ret) { 348 perror("ptrace(PTRACE_GETREGSET) failed"); 349 return TEST_FAIL; 350 } 351 352 for (i = 0; i < 32; i++) 353 regs->fpr[i] = val; 354 355 ret = ptrace(PTRACE_SETFPREGS, child, NULL, regs); 356 if (ret) { 357 perror("ptrace(PTRACE_GETREGSET) failed"); 358 return TEST_FAIL; 359 } 360 return TEST_PASS; 361 } 362 363 int show_ckpt_fpr(pid_t child, unsigned long *fpr) 364 { 365 struct fpr_regs *regs; 366 struct iovec iov; 367 int ret, i; 368 369 regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs)); 370 iov.iov_base = regs; 371 iov.iov_len = sizeof(struct fpr_regs); 372 373 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov); 374 if (ret) { 375 perror("ptrace(PTRACE_GETREGSET) failed"); 376 return TEST_FAIL; 377 } 378 379 if (fpr) { 380 for (i = 0; i < 32; i++) 381 fpr[i] = regs->fpr[i]; 382 } 383 384 return TEST_PASS; 385 } 386 387 int write_ckpt_fpr(pid_t child, unsigned long val) 388 { 389 struct fpr_regs *regs; 390 struct iovec iov; 391 int ret, i; 392 393 regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs)); 394 iov.iov_base = regs; 395 iov.iov_len = sizeof(struct fpr_regs); 396 397 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov); 398 if (ret) { 399 perror("ptrace(PTRACE_GETREGSET) failed"); 400 return TEST_FAIL; 401 } 402 403 for (i = 0; i < 32; i++) 404 regs->fpr[i] = val; 405 406 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CFPR, &iov); 407 if (ret) { 408 perror("ptrace(PTRACE_GETREGSET) failed"); 409 return TEST_FAIL; 410 } 411 return TEST_PASS; 412 } 413 414 /* GPR */ 415 int show_gpr(pid_t child, unsigned long *gpr) 416 { 417 struct pt_regs *regs; 418 int ret, i; 419 420 regs = (struct pt_regs *) malloc(sizeof(struct pt_regs)); 421 if (!regs) { 422 perror("malloc() failed"); 423 return TEST_FAIL; 424 } 425 426 ret = ptrace(PTRACE_GETREGS, child, NULL, regs); 427 if (ret) { 428 perror("ptrace(PTRACE_GETREGSET) failed"); 429 return TEST_FAIL; 430 } 431 432 if (gpr) { 433 for (i = 14; i < 32; i++) 434 gpr[i-14] = regs->gpr[i]; 435 } 436 437 return TEST_PASS; 438 } 439 440 int write_gpr(pid_t child, unsigned long val) 441 { 442 struct pt_regs *regs; 443 int i, ret; 444 445 regs = (struct pt_regs *) malloc(sizeof(struct pt_regs)); 446 if (!regs) { 447 perror("malloc() failed"); 448 return TEST_FAIL; 449 } 450 451 ret = ptrace(PTRACE_GETREGS, child, NULL, regs); 452 if (ret) { 453 perror("ptrace(PTRACE_GETREGSET) failed"); 454 return TEST_FAIL; 455 } 456 457 for (i = 14; i < 32; i++) 458 regs->gpr[i] = val; 459 460 ret = ptrace(PTRACE_SETREGS, child, NULL, regs); 461 if (ret) { 462 perror("ptrace(PTRACE_GETREGSET) failed"); 463 return TEST_FAIL; 464 } 465 return TEST_PASS; 466 } 467 468 int show_ckpt_gpr(pid_t child, unsigned long *gpr) 469 { 470 struct pt_regs *regs; 471 struct iovec iov; 472 int ret, i; 473 474 regs = (struct pt_regs *) malloc(sizeof(struct pt_regs)); 475 if (!regs) { 476 perror("malloc() failed"); 477 return TEST_FAIL; 478 } 479 480 iov.iov_base = (u64 *) regs; 481 iov.iov_len = sizeof(struct pt_regs); 482 483 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov); 484 if (ret) { 485 perror("ptrace(PTRACE_GETREGSET) failed"); 486 return TEST_FAIL; 487 } 488 489 if (gpr) { 490 for (i = 14; i < 32; i++) 491 gpr[i-14] = regs->gpr[i]; 492 } 493 494 return TEST_PASS; 495 } 496 497 int write_ckpt_gpr(pid_t child, unsigned long val) 498 { 499 struct pt_regs *regs; 500 struct iovec iov; 501 int ret, i; 502 503 regs = (struct pt_regs *) malloc(sizeof(struct pt_regs)); 504 if (!regs) { 505 perror("malloc() failed\n"); 506 return TEST_FAIL; 507 } 508 iov.iov_base = (u64 *) regs; 509 iov.iov_len = sizeof(struct pt_regs); 510 511 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov); 512 if (ret) { 513 perror("ptrace(PTRACE_GETREGSET) failed"); 514 return TEST_FAIL; 515 } 516 517 for (i = 14; i < 32; i++) 518 regs->gpr[i] = val; 519 520 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CGPR, &iov); 521 if (ret) { 522 perror("ptrace(PTRACE_GETREGSET) failed"); 523 return TEST_FAIL; 524 } 525 return TEST_PASS; 526 } 527 528 /* VMX */ 529 int show_vmx(pid_t child, unsigned long vmx[][2]) 530 { 531 int ret; 532 533 ret = ptrace(PTRACE_GETVRREGS, child, 0, vmx); 534 if (ret) { 535 perror("ptrace(PTRACE_GETVRREGS) failed"); 536 return TEST_FAIL; 537 } 538 return TEST_PASS; 539 } 540 541 int show_vmx_ckpt(pid_t child, unsigned long vmx[][2]) 542 { 543 unsigned long regs[34][2]; 544 struct iovec iov; 545 int ret; 546 547 iov.iov_base = (u64 *) regs; 548 iov.iov_len = sizeof(regs); 549 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVMX, &iov); 550 if (ret) { 551 perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVMX) failed"); 552 return TEST_FAIL; 553 } 554 memcpy(vmx, regs, sizeof(regs)); 555 return TEST_PASS; 556 } 557 558 559 int write_vmx(pid_t child, unsigned long vmx[][2]) 560 { 561 int ret; 562 563 ret = ptrace(PTRACE_SETVRREGS, child, 0, vmx); 564 if (ret) { 565 perror("ptrace(PTRACE_SETVRREGS) failed"); 566 return TEST_FAIL; 567 } 568 return TEST_PASS; 569 } 570 571 int write_vmx_ckpt(pid_t child, unsigned long vmx[][2]) 572 { 573 unsigned long regs[34][2]; 574 struct iovec iov; 575 int ret; 576 577 memcpy(regs, vmx, sizeof(regs)); 578 iov.iov_base = (u64 *) regs; 579 iov.iov_len = sizeof(regs); 580 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVMX, &iov); 581 if (ret) { 582 perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVMX) failed"); 583 return TEST_FAIL; 584 } 585 return TEST_PASS; 586 } 587 588 /* VSX */ 589 int show_vsx(pid_t child, unsigned long *vsx) 590 { 591 int ret; 592 593 ret = ptrace(PTRACE_GETVSRREGS, child, 0, vsx); 594 if (ret) { 595 perror("ptrace(PTRACE_GETVSRREGS) failed"); 596 return TEST_FAIL; 597 } 598 return TEST_PASS; 599 } 600 601 int show_vsx_ckpt(pid_t child, unsigned long *vsx) 602 { 603 unsigned long regs[32]; 604 struct iovec iov; 605 int ret; 606 607 iov.iov_base = (u64 *) regs; 608 iov.iov_len = sizeof(regs); 609 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVSX, &iov); 610 if (ret) { 611 perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVSX) failed"); 612 return TEST_FAIL; 613 } 614 memcpy(vsx, regs, sizeof(regs)); 615 return TEST_PASS; 616 } 617 618 int write_vsx(pid_t child, unsigned long *vsx) 619 { 620 int ret; 621 622 ret = ptrace(PTRACE_SETVSRREGS, child, 0, vsx); 623 if (ret) { 624 perror("ptrace(PTRACE_SETVSRREGS) failed"); 625 return TEST_FAIL; 626 } 627 return TEST_PASS; 628 } 629 630 int write_vsx_ckpt(pid_t child, unsigned long *vsx) 631 { 632 unsigned long regs[32]; 633 struct iovec iov; 634 int ret; 635 636 memcpy(regs, vsx, sizeof(regs)); 637 iov.iov_base = (u64 *) regs; 638 iov.iov_len = sizeof(regs); 639 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVSX, &iov); 640 if (ret) { 641 perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVSX) failed"); 642 return TEST_FAIL; 643 } 644 return TEST_PASS; 645 } 646 647 /* TM SPR */ 648 int show_tm_spr(pid_t child, struct tm_spr_regs *out) 649 { 650 struct tm_spr_regs *regs; 651 struct iovec iov; 652 int ret; 653 654 regs = (struct tm_spr_regs *) malloc(sizeof(struct tm_spr_regs)); 655 if (!regs) { 656 perror("malloc() failed"); 657 return TEST_FAIL; 658 } 659 660 iov.iov_base = (u64 *) regs; 661 iov.iov_len = sizeof(struct tm_spr_regs); 662 663 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_SPR, &iov); 664 if (ret) { 665 perror("ptrace(PTRACE_GETREGSET) failed"); 666 return TEST_FAIL; 667 } 668 669 if (out) 670 memcpy(out, regs, sizeof(struct tm_spr_regs)); 671 672 return TEST_PASS; 673 } 674 675 676 677 /* Analyse TEXASR after TM failure */ 678 inline unsigned long get_tfiar(void) 679 { 680 unsigned long ret; 681 682 asm volatile("mfspr %0,%1" : "=r" (ret) : "i" (SPRN_TFIAR)); 683 return ret; 684 } 685 686 void analyse_texasr(unsigned long texasr) 687 { 688 printf("TEXASR: %16lx\t", texasr); 689 690 if (texasr & TEXASR_FP) 691 printf("TEXASR_FP "); 692 693 if (texasr & TEXASR_DA) 694 printf("TEXASR_DA "); 695 696 if (texasr & TEXASR_NO) 697 printf("TEXASR_NO "); 698 699 if (texasr & TEXASR_FO) 700 printf("TEXASR_FO "); 701 702 if (texasr & TEXASR_SIC) 703 printf("TEXASR_SIC "); 704 705 if (texasr & TEXASR_NTC) 706 printf("TEXASR_NTC "); 707 708 if (texasr & TEXASR_TC) 709 printf("TEXASR_TC "); 710 711 if (texasr & TEXASR_TIC) 712 printf("TEXASR_TIC "); 713 714 if (texasr & TEXASR_IC) 715 printf("TEXASR_IC "); 716 717 if (texasr & TEXASR_IFC) 718 printf("TEXASR_IFC "); 719 720 if (texasr & TEXASR_ABT) 721 printf("TEXASR_ABT "); 722 723 if (texasr & TEXASR_SPD) 724 printf("TEXASR_SPD "); 725 726 if (texasr & TEXASR_HV) 727 printf("TEXASR_HV "); 728 729 if (texasr & TEXASR_PR) 730 printf("TEXASR_PR "); 731 732 if (texasr & TEXASR_FS) 733 printf("TEXASR_FS "); 734 735 if (texasr & TEXASR_TE) 736 printf("TEXASR_TE "); 737 738 if (texasr & TEXASR_ROT) 739 printf("TEXASR_ROT "); 740 741 printf("TFIAR :%lx\n", get_tfiar()); 742 } 743 744 void store_gpr(unsigned long *addr); 745 void store_fpr(float *addr); 746